1

I have a simple C program as follows:

int a = 10;
int b = 20;
int sum = 0;

void add() { sum = a + b; }

int main() {
  add();
  return 0;
}

I compile this for risc-v with the following command and specify that .text segment should start at 0x1000.

riscv32-unknown-elf-gcc -static -T elf32lriscv.x -Wl,-Ttext-segment=0x1000 -Wl,-Map=add.elf.map -o add.elf add.c

If I print the info of the file using gdb, I see the following:

(gdb) i files
Symbols from "/home/mango/myp/risc-v/prog/add.elf".
Local exec file:
        `/home/mango/myp/risc-v/prog/add.elf', file type elf32-littleriscv.
        Entry point: 0x108c
        0x00001074 - 0x0000159c is .text
        0x0000259c - 0x000025a0 is .eh_frame
        0x000025a0 - 0x000025a8 is .init_array
        0x000025a8 - 0x000025ac is .fini_array
        0x000025b0 - 0x000029d8 is .data
        0x000029d8 - 0x000029ec is .sdata
        0x000029ec - 0x000029f0 is .sbss
        0x000029f0 - 0x00002a0c is .bss

Is there a simple way to dump the memory starting from 0x1074 to 0x2a0c?

The dump memory command requires a start and end address, but since this changes based on the program, I'd prefer to be able to auto-dump this value. Also, this is clearly accessible within gdb, is there a way to get this automatically?

My end goal is to create a command file for gdb and pass that as follows to automate the memory dumping:

gdb --command=gdb_commands <filename>
Plasty Grove
  • 2,807
  • 5
  • 31
  • 42

1 Answers1

1

It doesn't look like sections are exposed in the GDB Python API.

You can write a trivial shell script along the lines of readelf -WS foo.elf | grep .bss to extract the end address and write the gdb_commands file for you.

Even better: have the script figure out end address and run GDB for you, no gdb_commands needed: gdb -ex 'dump binary memory $dump_filename $start $end' $elf

It might be better to extract the PT_LOAD segment instead of basing this script on sections to be more robust against section reordering.

Update:

I am guessing that you don't care about sections, but care about the segments.

that's very helpful. It shows me which part of the memory is writable. But it seems like it only includes data and sdata and not bss and sbss. Here is the output from gdb and from readelf: http://pastebin.com/HdW12MzS

Local exec file:
        `/home/mango/myp/risc-v/prog/add.elf', file type elf32-littleriscv.
        Entry point: 0x108c
        0x00001074 - 0x0000159c is .text
        0x0000259c - 0x000025a0 is .eh_frame
        0x000025a0 - 0x000025a8 is .init_array
        0x000025a8 - 0x000025ac is .fini_array
        0x000025b0 - 0x000029d8 is .data
        0x000029d8 - 0x000029ec is .sdata
        0x000029ec - 0x000029f0 is .sbss
        0x000029f0 - 0x00002a0c is .bss

readelf -Wl add.elf
...
Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x00001000 0x00001000 0x0059c 0x0059c R E 0x1000
  LOAD           0x00059c 0x0000259c 0x0000259c 0x00450 0x00470 RW  0x1000
 
 Section to Segment mapping:
  Segment Sections...
   00     .text 
   01     .eh_frame .init_array .fini_array .data .sdata .sbss .bss 

The output clearly shows that all the sections you care about are included in the second load segment.

The end of .bss is at 0x2a0c.

If I use the second segment with in memory size, I get 0x259c + 0x470 == 0x2a0c -- exactly the answer you are seeking.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • Thanks, I guess I'll just have to use a script to get this info. Could you please explain how I can get the `PT_LOAD` segment? I searched online and it's not immediately clear to me what this is for and how to extract it. – Plasty Grove Dec 11 '21 at 23:37
  • @PlastyGrove Examine output from `readelf -Wl $elf`. I am guessing that you don't care about sections, but care about the executable and readonly segments. See also https://stackoverflow.com/a/14382477/50617 – Employed Russian Dec 11 '21 at 23:56
  • Actually I only need the writable segments. To explain, I'm designing my own risc-v cpu. I run the program above on my own cpu (simulated) and then run it with an emulator (qemu) and compare the registers and the memory. It's easy enough to get the registers from gdb and print them to file. But memory location depends on the program. So I figured I'll just dump all the segments from both and compare them with each other. – Plasty Grove Dec 12 '21 at 02:05
  • @PlastyGrove Writable segment should be even easier -- there should generally only be one such segment. – Employed Russian Dec 12 '21 at 02:08
  • But the writeable segment consists of `data`, `sdata`, `bss`, `sbss`. So I'll need to dump at least these 4 sections. For which I need to know the exact ending address. This ending address in the `elf` file varies based on the program. – Plasty Grove Dec 12 '21 at 02:12
  • @PlastyGrove Did you _look_ at the output from `readelf -Wl`? The writable segment should _already_ include all these sections. – Employed Russian Dec 12 '21 at 02:29
  • Yes, that's very helpful. It shows me which part of the memory is writable. But it seems like it only includes `data` and `sdata` and not `bss` and `sbss`. Here is the output from gdb and from readelf: https://pastebin.com/HdW12MzS – Plasty Grove Dec 12 '21 at 02:52
  • @PlastyGrove I've updated the anwer. – Employed Russian Dec 12 '21 at 03:28