Skip to content

Commit

Permalink
Make sure symbol points to correct section.
Browse files Browse the repository at this point in the history
I was debugging #550, and I noticed a symbol was pointing to the
start of a section, but its shndx was set to SHN_UNDEF. Looking over
the code, I realized that for each section you create a corresponding
output section, but if the input section is mergeable, you also create
a fragment for it whose parent is MergeableSection, which in the end
will be copied into the output binary instead of the output section.

Since the symbol was pointing to the start of a mergeable section, I
realized that it is probably wrong to use the shndx of
`isec->output_section`, because that particular Chunk never actually
makes it to the list of final Chunks for mergeable sections.

Before:
```
$ eu-readelf -s ./target/debug/mold_test | grep _rustc
  Num:    Value   Size Type    Bind   Vis          Ndx Name
   77: 000d563c     34 OBJECT  LOCAL  DEFAULT    UNDEF __rustc_debug_gdb_scripts_section__

$ eu-readelf -S ./target/debug/mold_test
[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al
...
[22] .debug_gdb_scripts   PROGBITS     000d563c 0d563c 000022  0 A      0   0  1
...
```

After:
```
$ eu-readelf -s ./target/debug/mold_test | grep _rustc
  Num:    Value   Size Type    Bind   Vis          Ndx Name
   77: 000d563c     34 OBJECT  LOCAL  DEFAULT       22 __rustc_debug_gdb_scripts_section__

$ eu-readelf -S ./target/debug/mold_test
[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al
...
[22] .debug_gdb_scripts   PROGBITS     000d563c 0d563c 000022  0 A      0   0  1
...
```

Signed-off-by: Robert Bartlensky <bartlensky.robert@gmail.com>
  • Loading branch information
rbartlensky committed Aug 15, 2022
1 parent 0a8431b commit a595c48
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 2 deletions.
16 changes: 16 additions & 0 deletions elf/mold.h
Original file line number Diff line number Diff line change
Expand Up @@ -1787,6 +1787,7 @@ class Symbol {
bool has_plt(Context<E> &ctx) const;
bool has_got(Context<E> &ctx) const;

u64 get_st_shndx() const;
bool is_absolute() const;
bool is_relative() const { return !is_absolute(); }
bool is_local() const;
Expand Down Expand Up @@ -2279,6 +2280,21 @@ inline InputSection<E> *ObjectFile<E>::get_section(const ElfSym<E> &esym) {
return sections[get_shndx(esym)].get();
}

template <typename E>
inline u64 Symbol<E>::get_st_shndx() const {
// if we are pointing to a section fragment, then the parent section (which is
// mergeable) should contain the real st_shndx
if (SectionFragment<E> *frag = get_frag())
if (frag->is_alive)
return frag->output_section.shndx;

if (InputSection<E> *isec = get_input_section())
if (isec->is_alive)
return isec->output_section->shndx;

return SHN_UNDEF;
}

template <typename E>
inline u64 Symbol<E>::get_addr(Context<E> &ctx, bool allow_plt) const {
if (file && !file->is_dso) {
Expand Down
4 changes: 2 additions & 2 deletions elf/output-chunks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1220,10 +1220,10 @@ void get_output_esym(Context<E> &ctx, const Symbol<E> &sym, i64 strtab_offset,
out_esym.st_shndx = SHN_ABS;
out_esym.st_value = sym.get_addr(ctx);
} else if (sym.get_type() == STT_TLS) {
out_esym.st_shndx = isec->output_section->shndx;
out_esym.st_shndx = sym.get_st_shndx();
out_esym.st_value = sym.get_addr(ctx) - ctx.tls_begin;
} else {
out_esym.st_shndx = isec->output_section->shndx;
out_esym.st_shndx = sym.get_st_shndx();
out_esym.st_value = sym.get_addr(ctx, false);
out_esym.st_visibility = sym.visibility;
}
Expand Down

0 comments on commit a595c48

Please sign in to comment.