I am trying to perform loop bound analysis for ARMV7m code using Z3 for a big Framework.
I would like to find the memory address that are used by a certain function inside .elf file
for example in a function foo() I have the below basic block
ldr r1, [r3, #0x20]
strb r2, [r3, #6] {__elf_header}
str r2, [r3, #0x24] {__elf_header}
str r2, [r3, #0x20] {__elf_header}
mov r3, r1
cmp r1, #0
bne #0x89f6
How can I get the initial memory location used by this function [r3, #0x20] ? Are there memory segements for every function to access or is it random ?
Given that the above basic block is a loop. Is there a way to know the memory address that will be used during its execution ?
Does the compiler for example save a memory location address from 0x20 to 0x1234 to be only accessed during the execution of such basic block ? In another word, Is there a map between a function and the range of memory address used by it ?
It is confusing as to what you are asking. First off why would any linker put the effort into randomizing things? Perhaps there is one to intentionally make the output not repeatable. But a linker is just a program and normally will do things like process the items on the command line in order, and then process each object from beginning to end...not random.
So far the rest of this seems pretty straight forward just use the tools. Your comment implies gnu tools? Since this is in part tool specific you should have tagged it as such as you cannot really make generalizations across all toolchains ever created.
unsigned int one ( void )
{
return(1);
}
unsigned int two ( void )
{
return(2);
}
unsigned int three ( void )
{
return(3);
}
arm-none-eabi-gcc -O2 -c so.c -o so.o
arm-none-eabi-objdump -d so.o
so.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <one>:
0: e3a00001 mov r0, #1
4: e12fff1e bx lr
00000008 <two>:
8: e3a00002 mov r0, #2
c: e12fff1e bx lr
00000010 <three>:
10: e3a00003 mov r0, #3
14: e12fff1e bx lr
as shown they are all in .text, simple enough.
arm-none-eabi-gcc -O2 -c -ffunction-sections so.c -o so.o
arm-none-eabi-objdump -d so.o
so.o: file format elf32-littlearm
Disassembly of section .text.one:
00000000 <one>:
0: e3a00001 mov r0, #1
4: e12fff1e bx lr
Disassembly of section .text.two:
00000000 <two>:
0: e3a00002 mov r0, #2
4: e12fff1e bx lr
Disassembly of section .text.three:
00000000 <three>:
0: e3a00003 mov r0, #3
4: e12fff1e bx lr
and now each function has its own section name.
So the rest relies heavily on linking and there is no one linker script, you the programmer choose directly or indirectly and how the final binary (elf) is built is a direct result of that choice.
If you have something like this
.text : { *(.text*) } > rom
and nothing else with respect to these functions then all of them will land in this definition, but the linker script or instructions to the linker can indicate something else causing one or more to land in its own space.
arm-none-eabi-ld -Ttext=0x1000 so.o -o so.elf
arm-none-eabi-ld: warning: cannot find entry symbol _start; defaulting to 0000000000001000
arm-none-eabi-objdump -d so.elf
so.elf: file format elf32-littlearm
Disassembly of section .text:
00001000 <one>:
1000: e3a00001 mov r0, #1
1004: e12fff1e bx lr
00001008 <two>:
1008: e3a00002 mov r0, #2
100c: e12fff1e bx lr
00001010 <three>:
1010: e3a00003 mov r0, #3
1014: e12fff1e bx lr
and then of course
arm-none-eabi-nm -a so.elf
00000000 n .ARM.attributes
00011018 T __bss_end__
00011018 T _bss_end__
00011018 T __bss_start
00011018 T __bss_start__
00000000 n .comment
00011018 T __data_start
00011018 T _edata
00011018 T _end
00011018 T __end__
00011018 ? .noinit
00001000 T one <----
00000000 a so.c
00080000 T _stack
U _start
00001000 t .text
00001010 T three <----
00001008 T two <----
which is simply because there is a symbol table in the file
Symbol table '.symtab' contains 22 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00001000 0 SECTION LOCAL DEFAULT 1
2: 00000000 0 SECTION LOCAL DEFAULT 2
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00011018 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 FILE LOCAL DEFAULT ABS so.c
6: 00001000 0 NOTYPE LOCAL DEFAULT 1 $a
7: 00001008 0 NOTYPE LOCAL DEFAULT 1 $a
8: 00001010 0 NOTYPE LOCAL DEFAULT 1 $a
9: 00001008 8 FUNC GLOBAL DEFAULT 1 two
10: 00011018 0 NOTYPE GLOBAL DEFAULT 1 _bss_end__
11: 00011018 0 NOTYPE GLOBAL DEFAULT 1 __bss_start__
12: 00011018 0 NOTYPE GLOBAL DEFAULT 1 __bss_end__
13: 00000000 0 NOTYPE GLOBAL DEFAULT UND _start
14: 00011018 0 NOTYPE GLOBAL DEFAULT 1 __bss_start
15: 00011018 0 NOTYPE GLOBAL DEFAULT 1 __end__
16: 00001000 8 FUNC GLOBAL DEFAULT 1 one
17: 00011018 0 NOTYPE GLOBAL DEFAULT 1 _edata
18: 00011018 0 NOTYPE GLOBAL DEFAULT 1 _end
19: 00080000 0 NOTYPE GLOBAL DEFAULT 1 _stack
20: 00001010 8 FUNC GLOBAL DEFAULT 1 three
21: 00011018 0 NOTYPE GLOBAL DEFAULT 1 __data_start
but if
arm-none-eabi-strip so.elf
arm-none-eabi-nm -a so.elf
arm-none-eabi-nm: so.elf: no symbols
arm-none-eabi-objdump -d so.elf
so.elf: file format elf32-littlearm
Disassembly of section .text:
00001000 <.text>:
1000: e3a00001 mov r0, #1
1004: e12fff1e bx lr
1008: e3a00002 mov r0, #2
100c: e12fff1e bx lr
1010: e3a00003 mov r0, #3
1014: e12fff1e bx lr
The elf file format is somewhat trivial you can easily write code to parse it, you do not need a library or anything like that. And with simple experiments like these can easily understand how these tools work.
How can I get the initial memory used by this function ?
Assuming you mean the initial address assuming not relocated. You just read it out of the file. Simple.
Are there memory segments for every function to access or is it random ?
As demonstrated above, the command line option you mention later in a comment (should have been in the question, you should edit the question for completeness) does exactly that makes a custom section name per function. (what happens if you have the same non-global function name in two or more objects? you can easily figure this out on your own)
Nothing is random here, you would need to have a reason to randomize things for security or other, it is more often preferred that a tool outputs the same or at least similar results each time with the same inputs (some tools will embed a build date/time in the file and that may vary from one build to the next).
If you are not using gnu tools then binutils may still be very useful with parsing and displaying elf files anyway.
arm-none-eabi-nm so.elf
00011018 T __bss_end__
00011018 T _bss_end__
00011018 T __bss_start
00011018 T __bss_start__
00011018 T __data_start
00011018 T _edata
00011018 T _end
00011018 T __end__
00001000 T one
00080000 T _stack
U _start
00001010 T three
00001008 T two
nm so.elf (x86 binutils not arm)
00001000 t $a
00001008 t $a
00001010 t $a
00011018 T __bss_end__
00011018 T _bss_end__
00011018 T __bss_start
00011018 T __bss_start__
00011018 T __data_start
00011018 T _edata
00011018 T _end
00011018 T __end__
00001000 T one
00080000 T _stack
U _start
00001010 T three
00001008 T two
Or can build with clang and examine with gnu, etc. Obviously disassembly won't work, but some tools will.
If this is not what you were asking then you need to re-write your question or edit it so we can understand what you are actually asking.
Edit
I would like to know if there is a map between a function and the range of memory address used by it ?
In general no. The term function implies but is not limited to high level languages like C, etc. Where the machine code clearly has no clue nor should it and well optimized code does not necessarily have a single exit point from the function, much less a return marking the end. For architectures like the various arm instruction sets the return instruction is not the end of the "function", there is pool data that may follow.
But let's look at what gcc does.
unsigned int one ( unsigned int x )
{
return(x+1);
}
unsigned int two ( void )
{
return(one(2));
}
unsigned int three ( void )
{
return(3);
}
arm-none-eabi-gcc -O2 -S so.c
cat so.s
.cpu arm7tdmi
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 1
.eabi_attribute 30, 2
.eabi_attribute 34, 0
.eabi_attribute 18, 4
.file "so.c"
.text
.align 2
.global one
.arch armv4t
.syntax unified
.arm
.fpu softvfp
.type one, %function
one:
# Function supports interworking.
# args = 0, pretend = 0, frame = 0
# frame_needed = 0, uses_anonymous_args = 0
# link register save eliminated.
add r0, r0, #1
bx lr
.size one, .-one
.align 2
.global two
.syntax unified
.arm
.fpu softvfp
.type two, %function
two:
# Function supports interworking.
# args = 0, pretend = 0, frame = 0
# frame_needed = 0, uses_anonymous_args = 0
# link register save eliminated.
mov r0, #3
bx lr
.size two, .-two
.align 2
.global three
.syntax unified
.arm
.fpu softvfp
.type three, %function
three:
# Function supports interworking.
# args = 0, pretend = 0, frame = 0
# frame_needed = 0, uses_anonymous_args = 0
# link register save eliminated.
mov r0, #3
bx lr
.size three, .-three
.ident "GCC: (GNU) 10.2.0"
we see this is being placed in the file, but what does it do?
.size three, .-three
One reference says this is used so that the linker can remove the function if it is not used. And I have seen that feature in play so good to know (you could have looked this up just as easily as I did)
So in that context the info is there and you can extract it (lesson for the reader).
And then if you use this gcc compiler option that you mentioned
-ffunction-sections
Disassembly of section .text.one:
00000000 <one>:
0: e2800001 add r0, r0, #1
4: e12fff1e bx lr
Disassembly of section .text.two:
00000000 <two>:
0: e3a00003 mov r0, #3
4: e12fff1e bx lr
Disassembly of section .text.three:
00000000 <three>:
0: e3a00003 mov r0, #3
4: e12fff1e bx lr
[ 4] .text.one
PROGBITS 00000000 000034 000008 00 0 0 4
[00000006]: ALLOC, EXEC
[ 5] .rel.text.one
REL 00000000 0001a4 000008 08 12 4 4
[00000040]: INFO LINK
[ 6] .text.two
PROGBITS 00000000 00003c 000008 00 0 0 4
[00000006]: ALLOC, EXEC
[ 7] .rel.text.two
REL 00000000 0001ac 000008 08 12 6 4
[00000040]: INFO LINK
[ 8] .text.three
PROGBITS 00000000 000044 000008 00 0 0 4
[00000006]: ALLOC, EXEC
[ 9] .rel.text.three
REL 00000000 0001b4 000008 08 12 8 4
[00000040]: INFO LINK
That is giving us a size of the sections.
In general with respect to software compiled or in particular assembled, assume that a function doesn't have boundaries. As you can see above the one function is inlined into the two function, invisibly, so how big is an inlined function within another function? How many instances of a function are there in a binary? Which one do you want to monitor and know the size of, performance of, etc? Gnu has this feature with gcc, you can see if it is there with other languages or tools. Assume the answer is no, and then if you happen to find a way, then that is good.
Does the compiler saves a memory segment to be only accessed by a certain function ?
I have no idea what this means. The compiler doesn't make memory segments the linker does. How the binary is put into a memory image is a linker thing not a compiler thing for starters. Segments are just a way to communicate between tools that these bytes are for starters code (read only ideally), initialized data, or uninitialized data. Perhaps extending to read only data and then make up your own types.
If your ultimate goal is to find the bytes that represent the high level concept of "function" in memory (assuming no relocation, etc) by looking at the elf binary using the gnu toolchain. That is possible in theory.
The first thing we appear to know is that the OBJECT contains this information so that a linker feature can remove unused functions for size. But that does not automatically mean that the output binary from the linker also includes this information. You need to find where this .size lands in the object and then look for that in the final binary.
The compiler turns one language into another, often from a higher level to a lower level but not always depends on the compiler and input/output languages. C to assembly or C to machine code or what about Verilog to C++ for a simulation is that higher or lower? The terms .text, .data, .bss are not part of the language but more of a habit based on learned experience and helps as mentioned communicate with the linker so that the output binaries can be more controlled for various targets. Normally as shown above the compiler, gcc in this case, since no generalities can be made in this area across all tools and languages or even all C or C++ tools all the code for all the functions in the source file land in one .text segment by default. You have to do extra work to get something different. So the compiler in general does not make a "segment" or "memory segment" for each...In general. You already solved your problem it seems by using a command line option that turns every function into its own segment and now you have a lot more control over size and location, etc.
Just use the file format and/or the tools. This question or series of questions boils down into just go look at the elf file format. This is not a Stack Overflow question as questions seeking recommendations for external information is not for this site.
Does the compiler for example save a memory location address from 0x20 to 0x1234 to be only accessed during the execution of such basic block ? In another word, Is there a map between a function and the range of memory address used by it ?
"save"? the compiler does not link the linker links. Is that memory "only" accessed during the execution of that block? Well in a pure textbook theory yes, but in reality branch prediction and prefetch or cache line fills can also access that "memory".
Unless doing self-modifying code or using the mmu in interesting ways you do not re-use an address space for more than one function within an application. In general. So function foo() is implemented somewhere and bar() somewhere else. Hand written asm from the good old days you might have foo() branch right into the middle of bar() to save space, get better performance or to make the code harder to reverse engineer or whatever. But compilers are not that efficient, they do their best to turn concepts like functions into first off functional(ly equivalent to the high level code) and then second, if desired smaller or faster or both relative to a straight brute force conversion between languages. So barring inlining and tail (leaf?, I call it tail) optimizations and such, one could say there are some number of bytes at some address that define a compiled function. But due to the nature of processor technology you cannot assume those bytes are only accessed by the processor/chip/system busses only when executing that function.
I have a project that reads data from ethernet port and runs a set of algorithms on it.The program runs fine for a couple of hours and then produces the below shown error.
Could some suggest how to debug, find the line thats causing error ??
*** Error in `objs/x64Linux3gcc5.4.0/lidarToBoxes': malloc(): memory corruption: 0x00000000051fc640 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f230dc167e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8213e)[0x7f230dc2113e]
/lib/x86_64-linux-gnu/libc.so.6(__libc_malloc+0x54)[0x7f230dc23184]
/usr/lib/nvidia-384/tls/libnvidia-tls.so.384.111(+0x24c0)[0x7f2304e6e4c0]
======= Memory map: ========
00400000-00dc6000 r-xp 00000000 08:03 38407960 /home/sai/sai_workspace/avt_17_003/modules/lidarToBoxes/objs/x64Linux3gcc5.4.0/lidarToBoxes
00fc5000-00fcf000 r--p 009c5000 08:03 38407960 /home/sai/sai_workspace/avt_17_003/modules/lidarToBoxes/objs/x64Linux3gcc5.4.0/lidarToBoxes
00fcf000-00fd5000 rw-p 009cf000 08:03 38407960 /home/sai/sai_workspace/avt_17_003/modules/lidarToBoxes/objs/x64Linux3gcc5.4.0/lidarToBoxes
00fd5000-00ff0000 rw-p 00000000 00:00 0
0220b000-0614a000 rw-p 00000000 00:00 0
[heap]
7f22d0000000-7f22d0022000 rw-p 00000000 00:00 0
7f22d0022000-7f22d4000000 ---p 00000000 00:00 0
7f22d4000000-7f22d4021000 rw-p 00000000 00:00 0
7f22d4021000-7f22d8000000 ---p 00000000 00:00 0
7f22d8000000-7f22d8021000 rw-p 00000000 00:00 0
7f22d8021000-7f22dc000000 ---p 00000000 00:00 0
7f22dc000000-7f22dc07c000 rw-p 00000000 00:00 0
7f22dc07c000-7f22e0000000 ---p 00000000 00:00 0
7f22e0000000-7f22e0021000 rw-p 00000000 00:00 0
7f22e0021000-7f22e4000000 ---p 00000000 00:00 0
7f22e6ffe000-7f22e6fff000 ---p 00000000 00:00 0
7f22e6fff000-7f22e77ff000 rwxp 00000000 00:00 0
7f22e8000000-7f22e8021000 rw-p 00000000 00:00 0
7f22e8021000-7f22ec000000 ---p 00000000 00:00 0
7f22eeffe000-7f22eefff000 ---p 00000000 00:00 0
7f22eefff000-7f22ef7ff000 rwxp 00000000 00:00 0
7f22ef7ff000-7f22ef800000 ---p 00000000 00:00 0
7f22ef800000-7f22f0000000 rwxp 00000000 00:00 0
7f22f0000000-7f22f00a6000 rw-p 00000000 00:00 0
7f22f00a6000-7f22f4000000 ---p 00000000 00:00 0
7f22f4000000-7f22f4021000 rw-p 00000000 00:00 0
7f22f4021000-7f22f8000000 ---p 00000000 00:00 0
7f22f8000000-7f22f8021000 rw-p 00000000 00:00 0
7f22f8021000-7f22fc000000 ---p 00000000 00:00 0
7f22fc093000-7f22fc291000 rw-p 00000000 00:00 0
7f22fc291000-7f22fc491000 rw-s 00000000 00:09 323133
socket:[323133]
Thank you!
Based on this first message, the list of unsorted chunks for one particular arena has become corrupted:
* Error in `objs/x64Linux3gcc5.4.0/lidarToBoxes': malloc(): memory corruption: 0x00000000051fc640 *
You can see that by the fact that it says "malloc(): memory corruption" and not, for example "malloc(): memory corruption (fast)". The values at the end of the message vary between releases of glibc but in your particular case what you are seeing is the value of "victim" from code something like this:
while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) {
bck = victim->bk;
if (__builtin_expect (victim->size <= 2 * SIZE_SZ, 0)
|| __builtin_expect (victim->size > av->system_mem, 0))
malloc_printerr (check_action, "malloc(): memory corruption",
chunk2mem (victim));
size = chunksize(victim);
In my particular case I grabbed this from glibc-2.18/malloc/malloc.c because, based on the fact that you had one number after the message, your version of glibc seemed near 5.18 but that was just a guess. Your backtrace specifies "/lib/x86_64-linux-gnu/libc.so.6" as the library, which is a bit vague, but if you wanted to find more specific information one way to do so would be to do something like this:
ls -l /lib/x86_64-linux-gnu/libc.so.6
The output would likely show you that your path is a symbolic link, and the target of that link would be more informative. In this case I don't think you really need to know the exact version but having it would allow you to download matching glibc source if you see an error message from libc malloc and want to understand what it means.
So back to what that code shows you is that "victim" is set to point to the last entry of the doubly linked list for the arena recognized by av. It also shows you that the value at the end of the line is from "chunk2mem(victim)". In your case, with a 64 bit process, the macro chunk2mem is adding 16, so you can reconstruct the value of victim as 0x00000000051fc640-16 = 0x00000000051fc630.
You can look at what victim has by doing:
x/4gx 0x00000000051fc630
The second value shown will be the value of victim->size.
If you happen to have a core dump, you can probably use the free open source tool https://github.com/vmware/chap to gather more information because chap often detects such corruption at startup. To start it, use:
chap core-file-path
Given the likelihood that the size field is corrupted, it may also be helpful to understand how the adjacent allocation just prior to the one listed as 0x00000000051fc640 was being used. Possibly the corruption was due to a buffer overrun on that previous allocation. To see the contents of the previous allocation, type show allocation 51fc630 from the chap prompt. If chap tells you that the given address is not part of an allocation, use describe 51fc630 from the chap prompt to get an idea of what that allocation might be.
Before ruining the valgrind compile your program with adding -ggdb3 debug flag
gcc -o executable -std=c11 -Wall -ggdb3 main.c
To run valgrind, pass the executable as an argument
valgrind --leak-check=full \
--show-leak-kinds=all \
--track-origins=yes \
--verbose \
--log-file=valgrind-out.txt \
./executable
I'm use valgrind for detect many memory management bugs.
I am trying to set a breakpoint on the entry point in a stripped ELF. The ELF was compiled and stripped on Virtual Box Linux Machine.
root#xxxx:~# readelf -e yyyy_not_patched
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x650
Start of program headers: 64 (bytes into file)
Start of section headers: 6792 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 31
Section header string table index: 30
Program Headers point to:
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040
0x00000000000001f8 0x00000000000001f8 R E 0x8
INTERP 0x0000000000000238 0x0000000000000238 0x0000000000000238
0x000000000000001c 0x000000000000001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000000009ec 0x00000000000009ec R E 0x200000
LOAD 0x0000000000000dd8 0x0000000000200dd8 0x0000000000200dd8
0x0000000000000268 0x0000000000000278 RW 0x200000
DYNAMIC 0x0000000000000df0 0x0000000000200df0 0x0000000000200df0
0x00000000000001e0 0x00000000000001e0 RW 0x8
NOTE 0x0000000000000254 0x0000000000000254 0x0000000000000254
0x0000000000000044 0x0000000000000044 R 0x4
GNU_EH_FRAME 0x00000000000008a0 0x00000000000008a0 0x00000000000008a0
0x000000000000003c 0x000000000000003c R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x0000000000000dd8 0x0000000000200dd8 0x0000000000200dd8
0x0000000000000228 0x0000000000000228 R 0x1
"
When setting a breakpoint in the GDB I am getting "Cannot access memory at address 0x650"
root#xxxx:~# gdb yyyy_not_patched
Reading symbols from login_not_patched...(no debugging symbols found)...done.
(gdb) b *0x650
Breakpoint 1 at 0x650
(gdb) r
Starting program: /root/yyyy_not_patched
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x650
Any idea what could be the issue?
Any idea what could be the issue?
This:
Type: DYN (Shared object file)
means that you are looking at a position-independent executable (a special form of a shared library). Such executables are relocated to a random address before they start running, so setting breakpoint on unrelocated address 0x650 will not work.
What works:
(gdb) set stop-on-solib-events 1
(gdb) run
(gdb) info proc map
# Figure out where the executable got loaded
(gdb) b *($exe_load_address + 0x650)
Example:
$ readelf -h a.out | grep 'Entry point'
Entry point address: 0x620
$ gdb -q ./a.out
(gdb) set stop-on-solib-events 1
(gdb) run
Starting program: /tmp/a.out
Stopped due to shared library event (no libraries added or removed)
(gdb) info proc map
process 67394
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x555555554000 0x555555555000 0x1000 0x0 /tmp/a.out
0x555555754000 0x555555756000 0x2000 0x0 /tmp/a.out
0x7ffff7dda000 0x7ffff7dfd000 0x23000 0x0 /lib/x86_64-linux-gnu/ld-2.19.so
...
(gdb) b *(0x555555554000+0x620)
Breakpoint 1 at 0x555555554620
(gdb) c
Continuing.
Stopped due to shared library event:
Inferior loaded /lib/x86_64-linux-gnu/libc.so.6
(gdb) c
Continuing.
Breakpoint 1, 0x0000555555554620 in _start ()
(gdb) bt
#0 0x0000555555554620 in _start ()
I added two breakpoints in functions of one shared library (.so) and ran gdb 7.4 and attached it to a process.
Gdb hit the breakpoint and I ran n for several steps, and gdb reported the following errors(with bold text):
(gdb) b [function name]
Breakpoint 1 at 0xf1f28a49: file ../../../../../[file name].cpp, line 167.
Breakpoint 2 at 0xf1f2dae5: file ../../../../../[file name].cpp, line 60.
warning: Multiple breakpoints were set.
Use the "delete" command to delete unwanted breakpoints.
(gdb) c
Continuing.
[New Thread 0xcaafab90 (LWP 28480)]
[Thread 0xcaafab90 (LWP 28480) exited]
[New Thread 0xcaafab90 (LWP 29558)]
[New Thread 0xc8cb6b90 (LWP 29980)]
[Switching to Thread 0xc8cb6b90 (LWP 29980)]
Breakpoint 2, [function name] (ostr=..., clientResponse=..., httpProtocol=..., >reqType=...) at ../../../../../[file name].cpp:60
60 ../../../../../[file name].cpp: No such file or directory.
in ../../../../../[file name].cpp
(gdb) ni
0xf1f2daed 60 in ../../../../../[file name].cpp
(gdb) n
Breakpoint 1, [function name] (ostr=..., clientResponse=..., httpProtocol=..., >closeConn=..., asynchResponse=..., reqType=...)
at ../../../../../[file name].cpp:167
167 in ../../../../../[file name].cpp
(gdb) n
Warning:
Cannot insert breakpoint 0.
Error accessing memory address 0x36cc6dde: Input/output error.
0xf7082771 in siglongjmp () from /lib/libc.so.6
(gdb)
This is the output from /proc/[PID]/maps:
08048000-08146000 r-xp 00000000 08:03 293876
08146000-08150000 rw-p 000fe000 08:03 293876
08150000-099c8000 rw-p 08150000 00:00 0
[heap] c21f9000-c21fa000 ---p c21f9000 00:00 0
c21fa000-c29fa000 rwxp c21fa000 00:00 0 c29fa000-c29fb000 ---p
c29fa000 00:00 0 …… f1e1b000-f1e24000 rw-p f1e1b000 00:00
0 f1e24000-f2093000 r-xp 00000000 08:03 295549
.so f2093000-f2094000 ---p 0026f000 08:03 295549
.so f2094000-f2098000 r--p 0026f000 08:03 295549
.so f2098000-f209c000 rw-p 00273000 08:03 295549
.so f209c000-f209d000 rw-p f209c000 00:00 0
My questions are:
Gdb fails to insert internal breakpoint for ni command, but why does it try to access address 0x36cc6dde if the text section is at 0xf1******?That address is not included in the output of maps as you can see.
More general question, I was told shared library starts at 0x40000000 but why this is not the case in my environment?
The shared library is compiled with -fPIC. I hide some symbol names in the traces above.
This is probably related to http://sourceware.org/bugzilla/show_bug.cgi?id=13987. Please, could you try the latest FSF GDB HEAD (can be obtained from: git://sourceware.org/git/gdb.git).
We have PageHeap enabled and are running adplus on our system and recently have had a couple of "corrupted infix pattern for freed block" failures.
Can someone shed some light on what this means, what it might look like in the code and suggest steps on how best to proceed with resolving the issue?
===========================================================
Tue Jun 21 10:55:26.091 2011 (GMT+1): VERIFIER STOP 0000000E: pid 0x1710: corrupted infix pattern for freed block
07751000 : Heap handle
0920A830 : Heap block
00000018 : Block size
0920A844 : corruption address
Tue Jun 21 10:55:26.091 2011 (GMT+1):
===========================================================
This verifier stop is not continuable. Process will be terminated
when you use the `go' debugger command.
===========================================================
---
--- 1st chance CONTRL_C_OR_Debug_Break exception ----
---------------------------------------------------------------
CTRL-C was pressed to stop debugging this process!
When PageHeap is in use this exception can be an internal exception
---------------------------------------------------------------
Many thanks
Matt Peddlesden
It is described pretty well in this MSDN Library article. Classic heap corruption bug, your code is writing to a heap block after it was freed. If the address repeats well then you can set a data breakpoint with the debugger to trap the write. If it doesn't then you'll need the tool between your ears to hunt the bug down.
#Hans is right, it is heap corruption. If you configured appverif to capture stack traces, you can see where the memory was freed. You can also dump what was written at the "corruption address".
Here's an example where my code was decreasing the reference count on a Python object too many times. The stack indicates that the memory was free'd during garbage collection. The f0f0f0ef in the memory dump at the "corruption address" indicates this bogus refcount.
VERIFIER STOP 0000000E: pid 0x5ABC: Corrupted infix pattern for freed heap block.
FD531000 : Heap handle for the heap owning the block.
EE53B4F8 : Heap block being freed.
000001D8 : Size of the heap block.
EE53B508 : Corruption address.
=======================================
This verifier stop is not continuable. Process will be terminated
when you use the `go' debugger command.
=======================================
(5abc.52dc): Break instruction exception - code 80000003 (first chance)
eax=551402d4 ebx=00000000 ecx=000001a1 edx=000001dc esi=5513ec5c edi=fd531000
eip=551337f9 esp=005ebbc0 ebp=005ebdd4 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
vrfcore!VerifierStopMessageEx+0x599:
551337f9 cc int 3
0:000> dt verifier!_DPH_BLOCK_INFORMATION EE53B4F8-20
+0x000 StartStamp : 0xabcdaaa9
+0x004 Heap : 0x7d531000 Void
+0x008 RequestedSize : 0x1d8
+0x00c ActualSize : 0x200
+0x010 Internal : _DPH_BLOCK_INTERNAL_INFORMATION
+0x018 StackTrace : 0xff555dec Void
+0x01c EndStamp : 0xdcbaaaa9
0:000> dds 0xff555dec
ff555dec ffb57114
ff555df0 0000f802
ff555df4 00200000
ff555df8 54f4b5c6 verifier!AVrfpDphNormalHeapFree+0xb6
ff555dfc 54f49e63 verifier!AVrfDebugPageHeapFree+0xe3
ff555e00 7791f89e ntdll!RtlDebugFreeHeap+0x3c
ff555e04 7788995d ntdll!RtlpFreeHeap+0xd3d
ff555e08 77888bd8 ntdll!RtlFreeHeap+0x758
ff555e0c 5513af7b vrfcore!VfCoreRtlFreeHeap+0x2b
ff555e10 54ef58ea vfbasics!AVrfpRtlFreeHeap+0x11a
ff555e14 54ef72eb vfbasics!AVrfpHeapFree+0x10b
ff555e18 72b2016a MSVCR100!free+0x1c
ff555e1c 1dce003a python27!PyObject_GC_Del+0x3a
ff555e20 1dd89ce0 python27!type_dealloc+0x170
ff555e24 1dd84986 python27!tupledealloc+0x86
ff555e28 1dd89ee4 python27!type_clear+0x44
ff555e2c 1dcdedb7 python27!delete_garbage+0xf7
ff555e30 1dcdf28a python27!collect+0x3fa
ff555e34 1dcdf551 python27!collect_generations+0x51
ff555e38 1dd85ee9 python27!tuple_iter+0x49
ff555e3c 1dd38833 python27!PyObject_GetIter+0x53
ff555e40 1ddbf65a python27!PyEval_EvalFrameEx+0x6ba
ff555e44 1ddc3acd python27!fast_function+0x8d
ff555e48 1ddc39dd python27!call_function+0x30d
ff555e4c 1ddc1583 python27!PyEval_EvalFrameEx+0x25e3
ff555e50 1ddc3acd python27!fast_function+0x8d
ff555e54 1ddc39dd python27!call_function+0x30d
ff555e58 1ddc1583 python27!PyEval_EvalFrameEx+0x25e3
ff555e5c 1ddc3acd python27!fast_function+0x8d
ff555e60 1ddc39dd python27!call_function+0x30d
ff555e64 1ddc1583 python27!PyEval_EvalFrameEx+0x25e3
ff555e68 1ddc27e3 python27!PyEval_EvalCodeEx+0x8e3
0:000> dds
ff555e6c 1dd60b71 python27!function_call+0x101
ff555e70 1dd379aa python27!PyObject_Call+0x4a
ff555e74 1ddc35a2 python27!PyEval_CallObjectWithKeywords+0xf2
ff555e78 00000000
ff555e7c ff793d2c
0:000> dd EE53B4F8
ee53b4f8 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0
ee53b508 f0f0f0ef f0f0f0f0 f0f0f0f0 f0f0f0f0
ee53b518 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0
ee53b528 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0
ee53b538 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0
ee53b548 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0
ee53b558 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0
ee53b568 f0f0f0f0 f0f0f0f0 f0f0f0f0 f0f0f0f0