I executed following commands in gdb and console output is as follows:
Rohan_gdb$ set $var = 15
Rohan_gdb$ p $var
$5 = 0xf
Rohan_gdb$ set $var = (int *)10
Rohan_gdb$ p $var
$6 = (int *) 0xa
Rohan_gdb$ set $char = "abc"
Rohan_gdb$ p $char
$7 = "abc"
Rohan_gdb$ set $char = (char *)"xyz"
evaluation of this expression requires the program to have a function "malloc".
(here I got error)
Rohan_gdb$ p $char
$8 = "abc"
Rohan_gdb$
Here I am debugging with target and not native debugging. I am using GNU gdb (GDB) 7.2 version. Is it possible to solve using scripts.
I don't know how to solve your specific problem, but I ran across something similar. Given the age of the question, maybe this'll provide a clue.
The problem is that your script is trying to store away a value in a buffer and it must allocated a new buffer for that storage. The storage requirement is likely the result of the cast or because that second string is not in the constant strings within your binary.
To fix, either change your code to not require a malloc (which is a bit of hit or miss, as far as I can tell). Or make the malloc symbol available; load a symbol table that allows gdb to resolve the "_malloc" symbol.
All values are interpreted in the current language. This means, for example, that if the current source language is C/C++ then searching for the string “hello” includes the trailing \0. The null terminator can be removed from searching by using casts, e.g.: {char[5]}"hello".
https://sourceware.org/gdb/onlinedocs/gdb/Searching-Memory.html
Example:
https://github.com/PhoenixInteractiveNL/emuDownloadCenter/wiki/Emulator-wincpc <-> WinCPC is the Borland Delphi port of an Amstrad CPC emulator called vbCPC.
F:\flynns_WinCPC>gdb wincpc.exe<br>
GNU gdb (GDB) 7.6<br>
...<br>
This GDB was configured as "i686-pc-mingw32".<br>
...<br>
Reading symbols from F:\flynns_WinCPC\wincpc.exe...(no debugging symbols found)...done.<br>
(gdb) info files<br>
Symbols from "F:\flynns_WinCPC\wincpc.exe".<br>
Local exec file:<br>
`F:\flynns_WinCPC\wincpc.exe', file type pei-i386.<br>
Entry point: 0x558448<br>
0x00401000 - 0x005587ec is CODE<br>
0x00559000 - 0x0055f7f8 is DATA<br>
0x007bf000 - 0x007c1b88 is .idata<br>
0x007c3000 - 0x007c301f is .rdata<br>
0x007c4000 - 0x007db530 is .reloc<br>
0x007dc000 - 0x00861c00 is .rsrc<br>
(gdb) find 0x00401000,0x00861c00,'m','e','m','o','r','y'<br>
0x48b224<br>
0x48b2e8<br>
0x48b312<br>
0x48b33a<br>
0x48b354<br>
0x48c2cc<br>
0x48cfcb<br>
0x82d910<br>
0x841484<br>
0x8456f9<br>
10 patterns found.<br>
(gdb) find 0x00401000,0x00861c00, <strong>{char[6]}</strong> "memory"<br>
evaluation of this expression requires the program to have a function "malloc".<br>
Related
I want to define a new command which basically sets a breakpoint on a line, print a value of a certain variable and then continues execution. Unfortunately I am having issues. Here is the code I am using
(gdb) define print_and_continue
Type commands for definition of "print_and_continue".
End with a line saying just "end".
>break $arg0
>command $bpnum
>print $arg1
>continue
>end
>end
So I want to print the value of variable len which is defined in linked_list.h:109. And I execute the following code:
(gdb) print_and_continue linked_list.h:111 len
Breakpoint 1 at 0x388a: linked_list.h:111. (12 locations)
(gdb) r
...
Breakpoint 1, linked_list<test_struct<1>, 1>::remove_if<run_test<1, 1, 1>(std::vector<int, std::allocator<int> >&)::{lambda(test_struct<1> const&)#1}>(run_test<1, 1, 1>(std::vector<int, std::allocator<int> >&)::{lambda(test_struct<1> const&)#1}&&) (this=0x7fffffffdca0, condition=...) at linked_list.h:112
112 linked_list_node* prev = nullptr;
$1 = void
It seems like $arg1 in print function didn't get replaces by the actual argument. What am I doing wrong?
It seems like $arg1 in print function didn't get replaces by the actual argument.
I don't believe that's what is actually happening. Rather, everything following command $bpnum is attached to the newly-created breakpoint literally (without any expansion at all). You can see that happening with info break, which will show something like:
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000001136 at ...
print $arg1
continue
This is generally what you would want (deferring evaluating the argument until the time breakpoint is hit). Otherwise you would print current value of len if you use print len, when what you want is to print the value of len when the breakpoint is hit.
Of course, when the breakpoint is hit, there is no $arg1 (or $arg0) anywhere around, so you get the same output you'd get trying to print any other non-existent GDB variable.
What am I doing wrong?
You are using "quick hack of a language" (which is what the "native" GDB scripting language is), instead of using a proper programming language.
I am 99.99% certain that defining print_and_continue is possible (and probably quite easy) using embedded Python.
That said, I don't believe that print_and_continue is all that useful (in my 20+ years of using GDB, I never needed anything like that).
I am attempting to create a GDB user-defined command.
def decodecs
if $argc == 1
set $lowaddr=(short*)($arg0)
x /h $lowaddr
# The line below generates the error
set $lowaddr=$lowaddr & (short)0xfff8
x /h $lowaddr
set $lowaddr=$lowaddr >> (short)3
set $highaddr = (short*)($arg0+2)
x /h $highaddr
end
The error reported by GDB is:
Argument to arithmetic operation not a number or boolean
I have set the language to c. set language c
The error message is reported between the first and second 'x ...' outputs.
When I type the commands at the GDB prompt I do not get an error and the operation works as expected.
I am debugging a legacy program. It does not have GDB compatible debug symbols.
I am using a GDB cross for M68k, v4.3.2
This:
set $lowaddr=(short*)($arg0)
creates a GDB convenience variable of type short*. GDB will refuse bitwise operations on anything that is not a number, as can be trivially seen from trying:
(gdb) set $foo = (short*)0x1234
(gdb) p $foo
$1 = (short *) 0x1234
(gdb) p $foo & 0xff
Argument to arithmetic operation not a number or boolean.
So perform your operations on integers, and cast to pointer only when necessary. In your snippet you only use the pointer to x/h, which doesn't need a pointer at all.
I am writing a GDB macro to analyze the core and print a string. The output of string from core is "sp-4/0/2". Now I need to print only "sp", excluding others. I am not sure how to achieve this in GDB. Any pointers of this would be a great help.
Thanks in advance.
See, argv[1] is "sp-4/0/2"
(gdb) p argv[1]
$4 = 0x7fffffffe3fa "sp-4/0/2"
And this is only two first chars:
(gdb) printf "%.2s\n", argv[1]
sp
Or
(gdb) printf "%c%c\n", argv[1][0],argv[1][1]
sp
The following alternative works even when the size isn't known statically:
(gdb) p {char} argv[1]#2
I.e. you can replace the 2 by a variable or register value. This is useful when you are adding a breakpoint in e.g. write and don't have debug symbols available:
(gdb) b -qualified write # only match write, don't do globbing
(gdb) cond 1 $rdi == 2 # only when writing to stderr
(gdb) command 1
bt
p {char} $rsi#$rdx # print (partial) buffer
cont
The above works when the System V AMD64 calling convention is used, but can be easily adopted to the arm calling conventions by adapting the registers.
I'm writing a little BASIC compiler using LLVM, everything works fine. I'm trying to get debugging to work, and it's going fine, but I have a weird issue with variable names and GDB's print statement.
A little background on BASIC for those not familiar:
In BASIC, variable names use a symbol on the end to determine their type. So a variable x% would be integer, and variable x$ would be a string, and both can co-exist.
The statement DEFINT A-Z means that any variable starting with any letter from A to Z will be type INT, even without the trailing %. But, internally, my compiler will store the name mangled with the trailing % to avoid overlap with another variable with a trailing $.
Here is my little test program:
defint a-z
x = 5
y = 100
z = x + y
if x = 5 then
print "z=";z
else
print "z!=";z
end if
So 'x' is actually stored internally and put into the symbol table as x%.
OK, so I load my compiled EXE into GDB...
D:\dev\BasicParser>gdb t.exe
GNU gdb (GDB) 7.4
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from D:\dev\BasicParser\t.exe...done.
(gdb) b _jbc_main
Breakpoint 1 at 0x401000: file t.bas, line 1.
(gdb) r
Starting program: D:\dev\BasicParser\t.exe
[New Thread 1532.0x25b8]
Breakpoint 1, _jbc_main () at t.bas:1
1 defint a-z
(gdb) n
4 x = 5
(gdb) info address x%
Symbol "x%" is static storage at address 0x4263c4.
At this point, you can see that GDB recognizes the symbol x% because it recognizes and display it's address. But the following "print" fails:
(gdb) print x%
No symbol "x" in current context.
Hmmm... that's interesting ... it dropped the % symbol.
But I can look at the memory location where x% is stored and this looks correct:
(gdb) x 0x4263c4
0x4263c4 <x%>: 0x00000000
If I show all symbols I get this as expected:
(gdb) info variables
All defined variables:
File t.bas:
static i32 x%;
static i32 y%;
static i32 z%;
Continuing on, to show that x% does get modified by the code:
(gdb) n
5 y = 100
(gdb) print x%
No symbol "x" in current context.
(gdb) x 0x4263c4
0x4263c4 <x%>: 0x00000005
(gdb)
And as you can see, the memory that GDB thinks x% is at is definitely updated.
For some reason, the "print" command doesn't like the % symbol.
Here is the "info source" results on this module, you can see I didn't specify C as the language:
(gdb) info source
Current source file is t.bas
Compilation directory is D:\dev\BasicParser
Located in D:\dev\BasicParser\t.bas
Contains 18 lines.
Source language is minimal.
Compiled with DWARF 2 debugging format.
Does not include preprocessor macro info.
Any ideas for workarounds? I've been searching and searching and can't find a solution.
Thanks!
gdb simply interprets your command as modulo operation. It is not an error in gdb.
See, info source shows minimal for your file. This is from gdb's doc: http://sourceware.org/gdb/current/onlinedocs/gdb/Unsupported-Languages.html#Unsupported-Languages
In addition to the other fully-supported programming languages, GDB
also provides a pseudo-language, called minimal. It does not represent
a real programming language, but provides a set of capabilities close
to what the C or assembly languages provide.
So, what does this warning in your debugging session mean?
(gdb) print x%
No symbol "x" in current context.
Since minimal is a set of capabilities close C then gdb must iterpret this as trying to get remainder of division (http://en.wikipedia.org/wiki/Modulo_operation) - according to C programming language rules. So x is left arg, % is operation and the right arg is missing.
Let me show you example. This is a test C++ program that shows the minimal debugging session:
D:\src-c++\tests\test.vars>cat minimal.cpp
int main()
{
int k;
k = 1;
k = 2;
return 0;
}
And this is a debugging session:
D:\src-c++\tests\test.vars>gdb -q minimal.exe
Reading symbols from D:\src-c++\tests\test.vars\minimal.exe...done.
(gdb) start
Temporary breakpoint 1 at 0x4016be: file minimal.cpp, line 5.
Starting program: D:\src-c++\tests\test.vars/minimal.exe
[New Thread 2872.0x8c0]
Temporary breakpoint 1, main () at minimal.cpp:5
5 k = 1;
(gdb) show language
The current source language is "auto; currently c++".
(gdb) set language minimal
Warning: the current language does not match this frame.
(gdb) show language
The current source language is "minimal".
Warning: the current language does not match this frame.
(gdb) n
6 k = 2;
(gdb) print k
$1 = 1
(gdb) print k%
A syntax error in expression, near `'.
(gdb) print kk%
No symbol "kk" in current context.
Look -- No symbol "kk" in current context, the same error that you have.
Just a cross-reference, in case anybody else like me that might need help with this: I found this answer
In GDB, how to print the content of a symbol which has special characters?
where they indicate that you can quote names by starting with ampersand (&) and quote the name with single ticks ('), that is use something like
p &'my#complex.symbol%name'
x &'my#complex.symbol%name'
to inspect symbols with names beyond the usual C-style naming convention. I'm not completely clear what characters you can use at that point, but it seems like a good improvement.
As the other answer also points out, the GDB manual often refers to escaping symbol names just using single ticks (say something like p 'foo.c'). After some further reading I found in the GDB manual that this use of & seems to be an extension added for Windows support (see section titled "Features for Debugging MS Windows PE Executables", numbered 21.1.4 in the current edition), so I'm not sure if this may work outside of the Windows environment
This can be a very simple question, I'm am attempting to debug an application which generates the following segfault error in the kern.log
kernel: myapp[15514]: segfault at 794ef0 ip 080513b sp 794ef0 error 6 in myapp[8048000+24000]
Here are my questions:
Is there any documentation as to what are the diff error numbers on segfault, in this instance it is error 6, but i've seen error 4, 5
What is the meaning of the information at bf794ef0 ip 0805130b sp bf794ef0 and myapp[8048000+24000]?
So far i was able to compile with symbols, and when i do a x 0x8048000+24000 it returns a symbol, is that the correct way of doing it? My assumptions thus far are the following:
sp = stack pointer?
ip = instruction pointer
at = ????
myapp[8048000+24000] = address of symbol?
When the report points to a program, not a shared library
Run addr2line -e myapp 080513b (and repeat for the other instruction pointer values given) to see where the error is happening. Better, get a debug-instrumented build, and reproduce the problem under a debugger such as gdb.
If it's a shared library
In the libfoo.so[NNNNNN+YYYY] part, the NNNNNN is where the library was loaded. Subtract this from the instruction pointer (ip) and you'll get the offset into the .so of the offending instruction. Then you can use objdump -DCgl libfoo.so and search for the instruction at that offset. You should easily be able to figure out which function it is from the asm labels. If the .so doesn't have optimizations you can also try using addr2line -e libfoo.so <offset>.
What the error means
Here's the breakdown of the fields:
address - the location in memory the code is trying to access (it's likely that 10 and 11 are offsets from a pointer we expect to be set to a valid value but which is instead pointing to 0)
ip - instruction pointer, ie. where the code which is trying to do this lives
sp - stack pointer
error - Architecture-specific flags; see arch/*/mm/fault.c for your platform.
Based on my limited knowledge, your assumptions are correct.
sp = stack pointer
ip = instruction pointer
myapp[8048000+24000] = address
If I were debugging the problem I would modify the code to produce a core dump or log a stack backtrace on the crash. You might also run the program under (or attach) GDB.
The error code is just the architectural error code for page faults and seems to be architecture specific. They are often documented in arch/*/mm/fault.c in the kernel source. My copy of Linux/arch/i386/mm/fault.c has the following definition for error_code:
bit 0 == 0 means no page found, 1 means protection fault
bit 1 == 0 means read, 1 means write
bit 2 == 0 means kernel, 1 means user-mode
My copy of Linux/arch/x86_64/mm/fault.c adds the following:
bit 3 == 1 means fault was an instruction fetch
If it's a shared library
You're hosed, unfortunately; it's not possible to know where the
libraries were placed in memory by the dynamic linker after-the-fact.
Well, there is still a possibility to retrieve the information, not from the binary, but from the object. But you need the base address of the object. And this information still is within the coredump, in the link_map structure.
So first you want to import the struct link_map into GDB. So lets compile a program with it with debug symbol and add it to the GDB.
link.c
#include <link.h>
toto(){struct link_map * s = 0x400;}
get_baseaddr_from_coredump.sh
#!/bin/bash
BINARY=$(which myapplication)
IsBinPIE ()
{
readelf -h $1|grep 'Type' |grep "EXEC">/dev/null || return 0
return 1
}
Hex2Decimal ()
{
export number="`echo "$1" | sed -e 's:^0[xX]::' | tr '[a-f]' '[A-F]'`"
export number=`echo "ibase=16; $number" | bc`
}
GetBinaryLength ()
{
if [ $# != 1 ]; then
echo "Error, no argument provided"
fi
IsBinPIE $1 || (echo "ET_EXEC file, need a base_address"; exit 0)
export totalsize=0
# Get PT_LOAD's size segment out of Program Header Table (ELF format)
export sizes="$(readelf -l $1 |grep LOAD |awk '{print $6}'|tr '\n' ' ')"
for size in $sizes
do Hex2Decimal "$size"; export totalsize=$(expr $number + $totalsize); export totalsize=$(expr $number + $totalsize)
done
return $totalsize
}
if [ $# = 1 ]; then
echo "Using binary $1"
IsBinPIE $1 && (echo "NOT ET_EXEC, need a base_address..."; exit 0)
BINARY=$1
fi
gcc -g3 -fPIC -shared link.c -o link.so
GOTADDR=$(readelf -S $BINARY|grep -E '\.got.plt[ \t]'|awk '{print $4}')
echo "First do the following command :"
echo file $BINARY
echo add-symbol-file ./link.so 0x0
read
echo "Now copy/paste the following into your gdb session with attached coredump"
cat <<EOF
set \$linkmapaddr = *(0x$GOTADDR + 4)
set \$mylinkmap = (struct link_map *) \$linkmapaddr
while (\$mylinkmap != 0)
if (\$mylinkmap->l_addr)
printf "add-symbol-file .%s %#.08x\n", \$mylinkmap->l_name, \$mylinkmap->l_addr
end
set \$mylinkmap = \$mylinkmap->l_next
end
it will print you the whole link_map content, within a set of GDB command.
It itself it might seems unnesseray but with the base_addr of the shared object we are about, you might get some more information out of an address by debuging directly the involved shared object in another GDB instance.
Keep the first gdb to have an idee of the symbol.
NOTE : the script is rather incomplete i suspect you may add to the second parameter of add-symbol-file printed the sum with this value :
readelf -S $SO_PATH|grep -E '\.text[ \t]'|awk '{print $5}'
where $SO_PATH is the first argument of the add-symbol-file
Hope it helps