Get parameters of public symbols in WinDBG - windbg

I'm debugging an application with WinDBG and the PDB files contain only public symbols, so the "k" command shows only the function names in a call stack. How I can show parameters, too?
I already figured out that I can show decorated names by enabling ".symopt- 2",
so I can use the "undname.exe" that comes with Visual Studio to get the parameters from a decorated name. Essentially, I want that WinDBG does the same thing. Is that possible? Is there a plugin for this?
Many thanks in advance!
(PS: Visual Studio shows the parameters, so it probably does this by default)

the tool dbh.exe in windbg package has an undec command and a -d command line option which you can leverage by loading the exe in a sepearte cmd line window at the same base address as in windbg and examining like below this involves manual copy pasting of the decorated name
an example
dbh -d classmagic.exe
classmagic [1000000]: b 1350000 <-- base as loaded in windbg
classmagic [1350000]: a 1351000
?somecrap##YAHHMND#Z
name : ?somecrap##YAHHMND#Z
addr : 1351000
size : 0
flags : 400000
type : 0
modbase : 1350000
value : 0
reg : 0
scope : SymTagNull (0)
tag : SymTagPublicSymbol (a)
index : 1
classmagic [1350000]: undec ?somecrap##YAHHMND#Z
?somecrap##YAHHMND#Z =
int __cdecl somecrap(int,float,double,char)
classmagic [1350000]:
if you need automation and can accept or improve regex as approriate
1) you should have the gnuwin32 port of unix/linux sed.exe in path (to strip modname from k1 output )
2) instead of undname.exe you should have vc++filt in path
3) you should be able to run the windbg .shell command
4) redecorate the function name with .symopt- symopt_undname
5) run this one liner .shell -ci "k1" sed s/.*!//g | vc++filt
k1 use only one frame (top of stack)
.shell -ci takes a windbg command and passes the commands output to an external application
sed strips the module name and the bang character xxxxx! and pipes it to vc++filt
vc++filt de-mangles the symbol name and returns back the formal
function name to windbg screen
an example below
0:000> k1
ChildEBP RetAddr
001cf904 013513b5 classmagic!?somecrap##YAHHMND#Z
0:000> .shell -ci "k1" sed s/.*!//g | vc++filt
ChildEBP RetAddr
int __cdecl somecrap(int,float,double,char)

It depends on the type of symbols available.
Public symbols, don't contain information about formal parameters. This is explained to great length here (note: this page is also available in the windbg help file, search for "Public and Private Symbols").
Functions, on the other hand, are included both in the private symbol
data and public symbol table, but while the private symbol data
includes the function name, address, FPO records, input parameter
names and types, and output type, the public symbol table includes
just the function name, address, and FPO record.
x, ln (or some other commands like .fnent) should give you this kind of information.
Example with notepad:
0:004> x notepad!RestoreFmt
00007ff7`471251a8 notepad!RestoreFmt (<no parameter info>)
0:004> ln notepad!RestoreFmt
Browse module
Set bu breakpoint
(00007ff7`471251a8) notepad!RestoreFmt | (00007ff7`471251f8) notepad!SaveFile
Exact matches:
notepad!RestoreFmt (<no parameter info>)
Note that <no parameter info> clearly states that the symbols don't contain the required information.
The same applied to another program with private symbolic information:
C++ code:
bool DiskReaderWriter::ReadDisk(off_t offset, size_t size_to_read, std::vector<BYTE>& buffer)
Windbg :
0:001> x drive_rw!DiskReaderWriter::ReadDisk
00000000`00d202c0 drive_rw!DiskReaderWriter::ReadDisk (long, unsigned int, class std::vector<unsigned char,std::allocator<unsigned char> > *)
0:001> ln drive_rw!DiskReaderWriter::ReadDisk
Browse module
Set bu breakpoint
g:\app\cpp\drive_rw\diskreaderwriter.cpp(72)
(00000000`00d202c0) drive_rw!DiskReaderWriter::ReadDisk | (00000000`00d20410) drive_rw!std::_Iterator_base12::_Adopt
Exact matches:
drive_rw!DiskReaderWriter::ReadDisk (long, unsigned int, class std::vector<unsigned char,std::allocator<unsigned char> > *)

Related

How to get ioctl command value of the given driver?

How to get ioctl command value (integer value) of the given driver, which is not part of kernel source tree.
Example
#define ioctl_cmd _IOW('a', 1, struct example*)
I need an integer value of the command ioctl_cmd without actually modifying the driver.
The _IOW(type,nr,size) macro is defined for userspace code by #include <linux/ioctl.h>. The actual source of the macro is in "/usr/include/asm-generic/ioctl.h".
One way to get the integer value of the ioctl command value is to print it to the terminal in a C program:
#include <stdio.h>
#include <linux/ioctl.h>
#include "your_driver_ioctls.h" // defines `ioctl_cmd`
int main(void)
{
printf("ioctl_cmd = %u (0x%x)\n", ioctl_cmd, ioctl_cmd);
}
Alternatively, you can look at the definition of _IOW in the source to see how the ioctl command code is composed:
Bits 31 to 30 indicate the direction of transfer of the memory pointed to by the optional third argument of the ioctl() call:
_IOC_NONE = 0 (no direction)
_IOC_WRITE = 1 (userland is writing to kernel)
_IOC_READ = 2 (userland is reading from kernel)
_IOC_WRITE | _IOC_READ = 3 (userland is writing to and reading from kernel)
The _IOW(type,nr,size) macro sets the direction to _IOC_WRITE.
Bits 29 to 16 indicate the 14-bit size of the memory pointed to by the optional third argument of the ioctl() call. The _IOW(type,nr,size) macro sets this to the size of the type specified in the third parameter of the macro call (sizeof(size)).
Bits 15 to 8 indicate the 8-bit "type number" of the ioctl command code. Historically, a single ASCII character value was used for the type number, but any unsigned number up to 255 can actually be used. All the ioctl command codes defined for a device generally use the same type number. The _IOW(type,nr,size) macro sets this to the first parameter of the macro call (type).
Bits 7 to 0 indicate the 8-bit "function number" of the ioctl command code. The _IOW(type,nr,size) macro sets this to the second parameter of the macro call (nr).
Note that the above way of defining ioctl command codes is mostly just a convention. In particular, earlier subsystems such as TTY use a simpler scheme consisting of just a "type number" and a "function number").
Your #define ioctl_cmd _IOW('a', 1, struct example*) is unusual because it says that the optional third argument of the ioctl() call points to a struct example* and the size of that would be 4 or 8 (depending on the size of pointers in userspace). More conventionally, it would be defined as _IOW('a', 1, struct example).

windbg help missing kernel32 function

I am trying to follow this tutorial here https://www.microsoftpressstore.com/articles/article.aspx?p=2201303 specifically the part where it mentions x kernel32!writeprocessmemory
I am unable to find the method kernel32!WriteProcessMemory = even though documentation mentions it but i can find
kernel32!_imp__WriteProcessMemory and kernel32!WriteProcessMemoryStub. I am new to windbg and trying to follow the tutorial so i am not sure if this method has been deprecated and if so, what is it's substitute and how do we achieve similar functionality.
Thanks
The exported WriteProcessMemory function in fact points to the kernel32!WriteProcessMemoryStub stub which itself jumps onto the kernel32!__imp_WriteProcessMemory which redirects to the kernelbase DLL which is the "real" location for this function.
Let's check with a link dump:
C:>link /dump /exports c:\windows\system32\kernel32.dll | findstr /I WriteProcess
1579 62A 00036C50 WriteProcessMemory
0x36C50 is the RVA where the function "WriteProcessMemory" resides in kernel32 (as given by the export table). Now in windbg:
0:007> ln kernel32 + 0x36c50
Browse module
Set bu breakpoint
(00007ff9`4a6e6c50) KERNEL32!WriteProcessMemoryStub | (00007ff9`4a6e6c60) KERNEL32!ZombifyActCtxStub
We have an exact match which is in fact the KERNEL32!WriteProcessMemoryStub function. If we look at it:
0:007> u KERNEL32!WriteProcessMemoryStub
KERNEL32!WriteProcessMemoryStub:
00007ff9`4a6e6c50 48ff2599150400 jmp qword ptr [KERNEL32!_imp_WriteProcessMemory (00007ff9`4a7281f0)]
00007ff9`4a6e6c57 cc int 3
We can see it's just a jump to KERNEL32!_imp_WriteProcessMemory (located somewhere in the .idata section of kernel32).
Now if we look at what is contained at this location, we have a pointer:
0:007> dp KERNEL32!_imp_WriteProcessMemory L1
00007ff9`4a7281f0 00007ff9`496f0ca0
If we ask windbg what is this pointer:
0:007> ln 00007ff9`496f0ca0
Browse module
Set bu breakpoint
(00007ff9`496f0ca0) KERNELBASE!WriteProcessMemory | (00007ff9`496f0dc4) KERNELBASE!OpenWow64CrossProcessWorkConnection
Exact matches:
KERNELBASE!WriteProcessMemory (void)
We can see that in fact the "real" location for the WriteProcessMemory is in fact in kernelbase.dll.
note: you can actually do the last two commands in one with dps:
0:007> dps KERNEL32!_imp_WriteProcessMemory L1
00007ff9`4a7281f0 00007ff9`496f0ca0 KERNELBASE!WriteProcessMemory
Windbg command used:
ln (List Nearest Symbols): given an address, find the nearest symbol.
u (unassemble): used to disassemble a function
dp (display memory): display memory (pointer sized).
dps(Display Words and Symbols): as dp but with symbolic information.

When to use quotes in command line? cp versus find

I'm wondering if there is some pattern or trick to remember when or when not to use quotes in command line arguments.
e.g. what is the difference between:
find -type f -name "*<extension-with-quotes>"
and
cp <extension-without-quotes> ../<new-folder>
One needs quotes and one does not, else it gives an error. Why?
You need quotes if you don't want the shell expanding the arguments, but instead want the argument passed through verbatim to whatever program you're trying to run. See, for example, the following program:
#include <stdio.h>
int main (int argc, char *argv[]) {
printf ("Argument count = %d\n", argc);
for (int i = 0; i < argc; i++)
printf (" %2d: [%s]\n", i, argv[i]);
return 0;
}
which outputs its argument count and arguments. The following transcript shows how it runs with and without quotes:
$ ./testprog "*.sh"
Argument count = 2
0: [./testprog]
1: [*.sh]
$ ./testprog *.sh
Argument count = 7
0: [./testprog]
1: [xmit.sh]
2: [gen.sh]
3: [morph.sh]
4: [prog.sh]
5: [mon.sh]
6: [test.sh]
So, for example, if you're in a directory with three log files, the shell will change your:
ls *.log
into:
ls a.log b.log c.log
before handing that list on to the ls program (the ls program will never see the *.log at all).
However, find expects a file pattern rather than a list of files, so it will want the *.log passed through as is, one single argument rather than three individual arguments expanded by the shell.
In fact, if you had only a.log in the current directory, an unquoted *.log would only find files called a.log regardless of how many other log files existed in the directories below. That's because find never saw the *.log, only the a.log that the shell expanded it to.
A similar example is with expr. If you want to know what three times seven is, you don't want to be doing:
expr 3 * 7
since the shell will first expand * into all the files in the current directory:
3 dallas_buyers_club.avi nsa_agent_list.txt whitehouse_bomb.odt 7
and expr won't be able to make much sense of that1. The correct way of doing it is along the lines of:
expr 3 '*' 7
in effect preserving the * so the program gets it unchanged.
1 Special note to the NSA, CIA, MPAA and other dark shadowy organisations formed to strike fear into the hearts of mortal men. That file list is fictional humour. I really don't want any men in dark suits showing up at my front door :-)

How to use command line arguments in Fortran?

GCC version 4.6
The Problem: To find a way to feed in parameters to the executable, say a.out, from the command line - more specifically feed in an array of double precision numbers.
Attempt: Using the READ(*,*) command, which is older in the standard:
Program test.f -
PROGRAM MAIN
REAL(8) :: A,B
READ(*,*) A,B
PRINT*, A+B, COMMAND_ARGUMENT_COUNT()
END PROGRAM MAIN
The execution -
$ gfortran test.f
$ ./a.out 3.D0 1.D0
This did not work. On a bit of soul-searching, found that
$./a.out
3.d0,1.d0
4.0000000000000000 0
does work, but the second line is an input prompt, and the objective of getting this done in one-line is not achieved. Also the COMMAND_ARGUMENT_COUNT() shows that the numbers fed into the input prompt don't really count as 'command line arguments', unlike PERL.
If you want to get the arguments fed to your program on the command line, use the (since Fortran 2003) standard intrinsic subroutine GET_COMMAND_ARGUMENT. Something like this might work
PROGRAM MAIN
REAL(8) :: A,B
integer :: num_args, ix
character(len=12), dimension(:), allocatable :: args
num_args = command_argument_count()
allocate(args(num_args)) ! I've omitted checking the return status of the allocation
do ix = 1, num_args
call get_command_argument(ix,args(ix))
! now parse the argument as you wish
end do
PRINT*, A+B, COMMAND_ARGUMENT_COUNT()
END PROGRAM MAIN
Note:
The second argument to the subroutine get_command_argument is a character variable which you'll have to parse to turn into a real (or whatever). Note also that I've allowed only 12 characters in each element of the args array, you may want to fiddle around with that.
As you've already figured out read isn't used for reading command line arguments in Fortran programs.
Since you want to read an array of real numbers, you might be better off using the approach you've already figured out, that is reading them from the terminal after the program has started, it's up to you.
The easiest way is to use a library. There is FLAP or f90getopt available. Both are open source and licensed under free licenses.
The latter is written by Mark Gates and me, just one module and can be learned in minutes but contains all what is needed to parse GNU- and POSIX-like command-line options. The first is more sophisticated and can be used even in closed-source projects. Check them out.
Furthermore libraries at https://fortranwiki.org/fortran/show/Command-line+arguments
What READ (*,*) does is that it reads from the standard input. For example, the characters entered using the keyboard.
As the question shows COMMAND_ARGUMENT_COUNT() can be used to get the number of the command line arguments.
The accepted answer by High Performance Mark show how to retrieve the individual command line arguments separated by blanks as individual character strings using GET_COMMAND_ARGUMENT(). One can also get the whole command line using GET_COMMAND(). One then has to somehow parse that character-based information into the data in your program.
I very simple cases you just need the program requires, for example, two numbers, so you read one number from arg 1 and another form arg 2. That is simple. Or you can read a triplet of numbers from a single argument if they are comma-separated like 1,2,3 using a simple read(arg,*) nums(1:3).
For general complicated command line parsing one uses libraries such as those mentioned in the answer by Hani. You have set them up so that the library knows the expected syntax of the command line arguments and the data it should fill with the values.
There is a middle ground, that is still relatively simple, but one already have multiple arguments, that correspond to Fortran variables in the program, that may or may not be present. In that case one can use the namelist for the syntax and for the parsing.
Here is an example, the man point is the namelist /cmd/ name, point, flag:
implicit none
real :: point(3)
logical :: flag
character(256) :: name
character(1024) :: command_line
call read_command_line
call parse_command_line
print *, point
print *, "'",trim(name),"'"
print *, flag
contains
subroutine read_command_line
integer :: exenamelength
integer :: io, io2
command_line = ""
call get_command(command = command_line,status = io)
if (io==0) then
call get_command_argument(0,length = exenamelength,status = io2)
if (io2==0) then
command_line = "&cmd "//adjustl(trim(command_line(exenamelength+1:)))//" /"
else
command_line = "&cmd "//adjustl(trim(command_line))//" /"
end if
else
write(*,*) io,"Error getting command line."
end if
end subroutine
subroutine parse_command_line
character(256) :: msg
namelist /cmd/ name, point, flag
integer :: io
if (len_trim(command_line)>0) then
msg = ''
read(command_line,nml = cmd,iostat = io,iomsg = msg)
if (io/=0) then
error stop "Error parsing the command line or cmd.conf " // msg
end if
end if
end subroutine
end
Usage in bash:
> ./command flag=T name=\"data.txt\" point=1.0,2.0,3.0
1.00000000 2.00000000 3.00000000
'data.txt'
T
or
> ./command flag=T name='"data.txt"' point=1.0,2.0,3.0
1.00000000 2.00000000 3.00000000
'data.txt'
T
Escaping the quotes for the string is unfortunately necessary, because bash eats the first quotes.

How to get the running Perl script's path and name (argv[0] in C)

In C / C++ (bash, too?) the first command-line argument, argv[0], is the binary filename (prefixed by an absolute or relative path as invoked by the user).
In Perl the first command-line argument $ARGV[0] is the first command-line argument after the path and name of the script.
How can a Perl script get the path and name that was used to invoke it?
Thanks!
$0 contains the name of the file containing the perl script being executed.
"In C / C++ (bash, too?) the first command-line argument, argv[0], is the binary filename"
is dead wrong, by the way. The ISO standard mandates no such thing.
From C99:
If the value of argc is greater than zero, the string pointed to by argv[0] represents the program name; argv[0][0] shall be the null character if the program name is not available from the host environment.
And notice that it states "represents the program name", not "is the location of the binary executable". That's because there's an earlier snippet which states:
... the array members argv[0] through argv[argc-1] inclusive shall contain pointers to strings, which are given implementation-defined values by the host environment prior to program startup."
It's quite legal for your argv[0] for the command "sleep 60" to be "pax's fantastic sleep utility" rather than "/bin/sleep".
In short, the environment doesn't have to provide a representation of the program and, even if it does, it doesn't have to be anything usable for locating the binary.
But, having bored you with my diatribe, Perl provides $0 or $PROGRAM_NAME (in that hideous "English" mode) for this purpose. See perlvar for details.