2

I have an assembly file. I will use this file to include a binary file like below:

.section .bindata

.global imrdls_start
.type imrdls_start, @object

.global imr_SW_DL_start
.type imr_SW_DL_start, @object

.section .bindata
.balign 64
imrdls_start:
imr_SW_DL_start:
    .incbin "file.bin"
    .balign 1
imr_SW_DL_end:
    .byte 0

Then in C file, I will cal to that variable and use the content of that binary file.

int main(void) {
    extern uint8_t imrdls_start;
    uint8_t *ptrToExpectedDL = &imrdls_start;

    for(int i = 0; i < 135; i++)
    {
        printf("0x%02x ", ptrToExpectedDL[i]);
        if((((i + 1) % 15) == 0)) printf("\n");
    }

    return EXIT_SUCCESS;
}

The thing is, after compiling and execute, the content of "file.bin" print out is not correct.

The expected result are: 00 1d 81 ff 00 fe 00 ff 00 1e 82 00 00 20 82 ...

The trash output print are: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 ...

Below is my compiler and linking option:

qcc -Vgcc_ntoaarch64le -c -Wp,-MMD,build/aarch64le-debug/src/imrdls.d,-MT,build/aarch64le-debug/src/imrdls.o -o build/aarch64le-debug/src/imrdls.o  -Wall -fmessage-length=0 -g -O0 -fno-builtin  src/imrdls.s
qcc -Vgcc_ntoaarch64le -c -Wp,-MMD,build/aarch64le-debug/src/Test.d,-MT,build/aarch64le-debug/src/Test.o -o build/aarch64le-debug/src/Test.o  -Wall -fmessage-length=0 -g -O0 -fno-builtin  src/Test.c
qcc -Vgcc_ntoaarch64le -o build/aarch64le-debug/Test   build/aarch64le-debug/src/Test.o build/aarch64le-debug/src/imrdls.o  

Any comments will be really helpful. Thank you.

  • You declared `extern uint8_t imrdls_start;` *inside* `main`, rather than global scope. Have you tried declaring it outside? It seems that it doesn't change the asm symbol name (https://godbolt.org/z/aiRMgh), but it's a bit odd. Also, you could just declare it as `extern uint8_t imrdls_start[]` so the compiler knows it's an array object. – Peter Cordes Dec 14 '18 at 04:41
  • What does your program print? What *should* it have printed? This isn't a [mcve]. – Peter Cordes Dec 14 '18 at 04:42
  • @PeterCordes Hi Peter, thank you for your comments. I just edited my question. I tried both your way before, declare as global and add "[]", but the issue is still remains. Regards. – Kiệt Phạm Dec 14 '18 at 04:49
  • So the "expected" bytes are what you get from `hexdump -C file.bin`? Are you sure there's no error or warning message when you build about file not found? Or is there possibly a different version of `file.bin` in another directory? Maybe `strace -f -efile gcc -c ...` to see which files the assembler accesses when building an object file from your asm source. – Peter Cordes Dec 14 '18 at 04:54
  • 1
    Yes @PeterCordes, I used hex dump. There's no error or warning when building. I sure about the file.bin because if i move it some where else, it will inform error no file. – Kiệt Phạm Dec 14 '18 at 05:15
  • Have you tried using `.byte 0x00, 0x1d, 0x81, ...` instead of `.incbin`, to see if the problem is `.incbin` or if there's some kind of linking / section problem? What segment of the ELF executable does the `.bindata` custom section get linked into? Is it part of the text segment like `.rodata`, or does it end up somewhere else? – Peter Cordes Dec 14 '18 at 05:20
  • 1
    @PeterCordes it is really strange that, i tried to use .byte 0x00, 0x1d, 0x81,.. as you said. The output value is still 7f 45 4c 46 02 01 01...It seem like i have to do something with the section .bindata like put it to RAM, do you have any ideas – Kiệt Phạm Dec 14 '18 at 05:33
  • Look at your file with `readelf -a` to see section/segment mappings, or write a linker script, or google up more info about custom ELF sections and what flags to give them. Or just put your data in `.section .rodata`, which is a standard section name that will definitely be mapped normally. If it still doesn't work in `.rodata`, then there's still some other problem, but that should do it. – Peter Cordes Dec 14 '18 at 05:42
  • 1
    @PeterCordes i just research about .section, and you are correct we have to put in into memory. I just figured out to use the .rodata then i see your comment :D. I'm really appreciate all your help. Thank you very much – Kiệt Phạm Dec 14 '18 at 05:55
  • @PeterCordes How you declare an external signal should not make a difference. – fuz Dec 14 '18 at 10:31
  • @fuz: it surprised me because I'm used to seeing `static int foo` inside a function get a name like `main::foo` (after name-mangling in C++). But of course that wouldn't make sense for `extern`, because there's be no way to define it in another compilation unit without a conflicting definition of the same function. So yeah, it turns out that an `extern` declaration inside a function doesn't change the symbol name. – Peter Cordes Dec 14 '18 at 10:37

2 Answers2

3

if you look at the trash output "7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00" you can see that it is same as the elf header. link

When one creates a new section using .section directive, one must provide the attributes and type for that section. replacing the first line in your assembly file with this should work:

.section .bindata , "a", @progbits

a marks the section as allocatable. ("aw" would also make it writeable, but you don't need that for constants. You'd use "aw" for an equivalent of .data, not .rodata.)

If no flags are specified, the default flags depend upon the section name. If the section name is not recognized, the default will be for the section to have none of the flags: it will not be allocated in memory, nor writable, nor executable. The section will contain data. Reference

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Rajnesh
  • 798
  • 5
  • 22
  • The OP confirmed that the hexdump of their file is what they expect. But well spotted that it's an ELF header- I'd guess those bytes are coming from the start of the linked executable the OP is creating. (And that apparently symbols in the custom section end up resolving to the start of the page where the executable file is mapped.) – Peter Cordes Dec 14 '18 at 12:15
  • 1
    Got the issue, When one creates a new section using .section directive, one must provide the attributes and type for that section. replacing the first line in your assembly file with ".section .bindata , "aw", @progbits" will do the work. Explanation: In my understanding as whole of your asm file code uses .bindata section, linker puts whole of the .o file in bindata section and because imrdls_start is pointing to the start of the bindata section, the .o file of you asm file gets printed. which is why we see the elf file header in the trash. – Rajnesh Dec 14 '18 at 13:31
  • Something like that sounds right, you should [edit] your answer to replace the wrong parts with the right info from your last comment. Especially the permissions + `@progbits` part is what gets the data mapped into memory, I think. – Peter Cordes Dec 14 '18 at 13:40
  • Thanks @PeterCordes – Rajnesh Dec 14 '18 at 14:14
  • There's no indication the OP wants the section to be writeable. They're only reading from it. It's better to make it read-only if possible, so it can be mapped shared. – Peter Cordes Dec 14 '18 at 14:37
1

Your data is in a section with a non-standard name, .bindata. I don't know where the linker puts it, but apparently it's not mapped into an executable segment that gets loaded (or memory mapped) from the file when you run the program.

Unless you really need to control the layout of the included data relative to compiler-generated read-only data, just put your data in .section .rodata.

(I'm surprised that the linker didn't complain, and that you didn't get a segfault at runtime. I would have hoped for at least a segfault instead of silently getting bogus data.)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847