Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect symtab entry #1061

Closed
mkornaukhov03 opened this issue Jul 19, 2023 · 2 comments
Closed

Incorrect symtab entry #1061

mkornaukhov03 opened this issue Jul 19, 2023 · 2 comments

Comments

@mkornaukhov03
Copy link

mkornaukhov03 commented Jul 19, 2023

How to reproduce:
I had gcc 8.3.0, but I suppose that it's reproducible on newer versions of it;
mold 1.11.0 (d4d93d7), but I suppose that it's reproducible on newer versions of it.
Let's generate an .o file with a lot of sections. For example,

def generate_file(file_id):
    ITER_CNT = 1000
    s = "#include <iostream>\n"
    
    for iter_id in range(0, ITER_CNT):
        s += 'int uninit_{}_{};\n'.format(file_id, iter_id)
        s += 'int zeroed_{}_{} = 0;\n'.format(file_id, iter_id)
        s += 'int init_{}_{} = {};\n'.format(file_id, iter_id, iter_id + file_id)
        s += 'static int static_{}_{} = {};\n'.format(file_id, iter_id, iter_id + file_id)
        s += 'int foo_{}_{}(){{ std::cout << {}; return {}; }}\n'.format(file_id, iter_id, iter_id + file_id, iter_id + file_id);
    return s;

if __name__ == "__main__":
    FILE_CNT = 50
    for file_id in range(0, FILE_CNT):
        with open('cpp/file{}.cpp'.format(file_id), 'w') as f:
            f.write(generate_file(file_id))

Then, let's compile each .cpp file with generating an extra section per data/function definition(/home/mkornaukhov/mold contains symlink ld -> /usr/bin/mold):

#!/bin/bash

for file in *.cpp; do
  g++ "$file" -B/home/mkornaukhov/mold  -ffunction-sections -fdata-sections -c -o "$file".o &
done

And then, let's collect all .o files in single .o file:

g++ -B/home/mkornaukhov/mold file*.o -r -nostdlib -ffunction-sections -fdata-sections -o total.o

After that, let's try to compile an executable:

g++ -B/home/mkornaukhov/mold total.o -o total.out

There's error:

mold: fatal: total.o: common local symbol?
collect2: error: ld returned 1 exit status

Meanwhile ld and lld handle it and fail when they cannot find main function.

I did some research:
Let's look at symbol table:

$ readelf -s total.o | grep " COM"
 65522: 0000000000000000     0 SECTION LOCAL  DEFAULT  COM 
131058: 0000000000000000     0 SECTION LOCAL  DEFAULT  COM 
196594: 0000000000000000     0 SECTION LOCAL  DEFAULT  COM 
262130: 0000000000000000     0 SECTION LOCAL  DEFAULT  COM

Mold creates entries of type SECTION with LOCAL binding and st_shndx equal to 65522 (= 0xfff2 = COM).
It's interesting that each entry of this pattern is equal to 0xfff2(=65522) modulo 0x10000(=65536).

Let's look at section header table:

$ readelf -S total.o | head -n1
There are 300118 section headers, starting at offset 0x1af5548
$ readelf -S total.o | grep "\[65522\]"
  [65522] .data._ZL13static PROGBITS         0000000000000000  002ed964

I found out that in case of sections number is greater (or equal) than 65522 (reserved index for SHN_COMMON) mold creates incorrect entries in symbol table, mentioned above.

@irdkwmnsb
Copy link

irdkwmnsb commented Jul 19, 2023

It looks like because there are just too many entries in the section header table that some entries indices are so large they overlap with the reserved header indices when writing the section table. As per linux elf format manpages
Maybe mold can add a check to not put symbols at those indices?

@rui314
Copy link
Owner

rui314 commented Jul 20, 2023

Thank you for your report. I will fix the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants