[ELF] Refactor ObjFile<ELFT>::initializeSymbols to enforce the invariant: InputFile...
authorFangrui Song <maskray@google.com>
Fri, 19 Jun 2020 16:05:28 +0000 (09:05 -0700)
committerFangrui Song <maskray@google.com>
Fri, 19 Jun 2020 16:05:37 +0000 (09:05 -0700)
commitc4d13f72a6599179f34481d6d848e9fce4ba5ef4
tree407e958f2a394330f54409fd58fbc7da1cbf0f41
parent2b87a44c493132de15b415424a5b5e9e1cdd9c83
[ELF] Refactor ObjFile<ELFT>::initializeSymbols to enforce the invariant: InputFile::symbols has non null entry

Fixes PR46348.

ObjFile<ELFT>::initializeSymbols contains two symbol iteration loops:

```
for each symbol
  if non-inheriting && non-local
    fill in this->symbols[i]

for each symbol
  if local
    fill in this->symbols[i]
  else
    symbol resolution
```

Symbol resolution can trigger a duplicate symbol error which will call
InputSectionBase::getObjMsg to iterate over InputFile::symbols.  If a
non-local symbol appears after the non-local symbol being resolved
(violating ELF spec), its `this->symbols[i]` entry has not been filled
in, InputSectionBase::getObjMsg will crash due to
`dyn_cast<Defined>(nullptr)`.

To fix the bug, reorganize the two loops to ensure this->symbols is
complete before symbol resolution. This enforces the invariant:
InputFile::symbols has none null entry when InputFile::getSymbols() is called.

```
for each symbol
  if non-inheriting
    fill in this->symbols[i]

for each symbol starting from firstGlobal
  if non-local
    symbol resolution
```

Additionally, move the (non-local symbol in local part of .symtab)
diagnostic from Writer<ELFT>::copyLocalSymbols() to initializeSymbols().

Reviewed By: grimar, jhenderson

Differential Revision: https://reviews.llvm.org/D81988
lld/ELF/InputFiles.cpp
lld/ELF/Writer.cpp
lld/test/ELF/invalid/symtab-sh-info-dup.test [new file with mode: 0644]
lld/test/ELF/invalid/symtab-sh-info.s