[PATCH] D80059: [ELF] Parse SHT_GNU_verneed and respect versioned undefined symbols in shared objects

George Rimar via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon May 18 03:10:41 PDT 2020


grimar added inline comments.


================
Comment at: lld/ELF/InputFiles.cpp:1217
+// sophisticated error checking in llvm-readobj because the value of diagnostics
+// is low.
+template <typename ELFT>
----------------
in llvm-readobj?


================
Comment at: lld/ELF/InputFiles.cpp:1219
+template <typename ELFT>
+std::vector<uint32_t> SharedFile::parseVerneed(const ELFFile<ELFT> &obj,
+                                               const typename ELFT::Shdr *sec) {
----------------
I have a feeling that this method does too much here.

In llvm-readelf we have the following method:

```
template <class ELFT>
Expected<std::vector<VerNeed>>
ELFDumper<ELFT>::getVersionDependencies(const Elf_Shdr *Sec) const;
```

One of possible solutions could be to refactor it and move the logic to `ELFFile<ELFT>` so that
it could be reused from LLD.

Or, if not, then the code here could be simplified a bit, see my comments below.


================
Comment at: lld/ELF/InputFiles.cpp:1226
+  const uint8_t *verneedBuf = obj.base() + sec->sh_offset;
+  const uint8_t *bufEnd = obj.base() + obj.getBufSize();
+  for (unsigned i = 0; i != sec->sh_info; ++i) {
----------------
I think you can use sec->sh_size?

```
const uint8_t *secEnd = obj.base() + sec->sh_size;
```

It should be enough to check that we are not going past the end of the section.


================
Comment at: lld/ELF/InputFiles.cpp:1231
+    // size.
+    if (verneedBuf + sizeof(typename ELFT::Verneed) > bufEnd ||
+        uintptr_t(verneedBuf) % sizeof(uint32_t) != 0) {
----------------
`>=` I think.


================
Comment at: lld/ELF/InputFiles.cpp:1235
+            Twine::utohexstr(verneedBuf - obj.base()));
+      return {};
+    }
----------------
What about introducing a helper lambda:

```
auto checkBuf = [](const uint8_t *Buf, const Twine& Name) {
  if (B < secEnd && uintptr_t(verneedBuf) % sizeof(uint32_t) == 0)
    return true;
  error(... invalid " + Name + " at ... )
  return false;
}
```

It should simplify the code a bit I guess.


================
Comment at: lld/ELF/InputFiles.cpp:1253
+              Twine::utohexstr(uint16_t(aux->vna_name)) + ") at offset 0x" +
+              Twine::utohexstr(vernauxBuf - obj.base()));
+        return {};
----------------
I am not sure such precise diagnostic is needed for LLD. It could be just: "error parsing SHT_GNU_verneed: broken vna_name" or just "error parsing SHT_GNU_verneed" for all errors here. So you'll be able to use a new helper lambda too.

I think it is imprortant that llvm-readelf/llvm-readobj is able to say what is wrong with the object, but probably no need to overcomplicate the code in LLD to report the details. Alternatively, `getVersionDependencies` code can be moved to `ELFFile<ELFT>` and reused, as I've mentioned earlier. With that LLD would report detailed errors, but do not do the parsing on its side.


================
Comment at: lld/ELF/InputFiles.h:367
+  template <typename ELFT>
+  std::vector<uint32_t> parseVerneed(const llvm::object::ELFFile<ELFT> &obj,
+                                     const typename ELFT::Shdr *sec);
----------------
It should probably be protected/private.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80059/new/

https://reviews.llvm.org/D80059





More information about the llvm-commits mailing list