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

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed May 20 08:43:14 PDT 2020


MaskRay added inline comments.


================
Comment at: lld/ELF/InputFiles.cpp:1235
+            Twine::utohexstr(verneedBuf - obj.base()));
+      return {};
+    }
----------------
grimar wrote:
> MaskRay wrote:
> > grimar wrote:
> > > 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.
> > The similar diagnostics occur twice. For `checkBuf`, we will need:
> > 
> > ```
> > if (!checkBuf(...))
> >   return false;
> > ```
> > 
> > The end result will be longer.
> I also do not think it is important to use `error()` for invalid objects. In many places
> LLD calls `fatal()`. Then you can simplify the code. E.g (I've not checked it):
> 
> 
> ```
>   ArrayRef<uint8_t> data =
>       CHECK(obj.template getSectionContentsAsArray<uint8_t>(sec), this);
>   const uint8_t *verneedBuf = data.begin();
> 
>   auto checkBuf = [&](uint8_t *buf, size_t size, size_t align) {
>     if (buf + size > data.end() || uintptr_t(buf) % align != 0)
>       fatal(toString(this) + ": unable to parse SHT_GNU_verneed");
>     return buf;
>   };
> 
>   for (unsigned i = 0; i != sec->sh_info; ++i) {
>     auto *vn = reinterpret_cast<const typename ELFT::Verneed *>(
>         checkBuf(verneedBuf, sizeof(typename ELFT::Verneed), sizeof(uint32_t)));
>     const uint8_t *vernauxBuf = verneedBuf + vn->vn_aux;
>     for (unsigned j = 0; j != vn->vn_cnt; ++j) {
>       auto *aux = reinterpret_cast<const typename ELFT::Vernaux *>(checkBuf(
>           vernauxBuf, sizeof(typename ELFT::Vernaux), sizeof(uint32_t)));
>       uint16_t version = aux->vna_other & VERSYM_VERSION;
>       if (version >= verneeds.size())
>         verneeds.resize(version + 1);
>       if (aux->vna_name >= this->stringTable.size())
>         fatal(toString(this) + ": unable to parse SHT_GNU_verneed");
>       verneeds[version] = aux->vna_name;
>       vernauxBuf += aux->vna_next;
>     }
>     verneedBuf += vn->vn_next;
>   }
>   return verneeds;
> }
> ```
Changed `error` to `fatal`. This saves 6 lines. A helper `checkBuf` may still be a bit unnecessary I think. I do want to give a bit more contex (Vernaux parsing error instead of Verneed parsing error).


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