[llvm] [Object] Extract format-agnostic BBAddrMap decoder (PR #188435)

Haohai Wen via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 2 01:33:01 PDT 2026


================
@@ -724,82 +724,86 @@ ELFFile<ELFT>::toMappedAddr(uint64_t VAddr, WarningHandler WarnHandler) const {
   return base() + Offset;
 }
 
-// Helper to extract and decode the next ULEB128 value as unsigned int.
-// Returns zero and sets ULEBSizeErr if the ULEB128 value exceeds the unsigned
-// int limit.
-// Also returns zero if ULEBSizeErr is already in an error state.
-// ULEBSizeErr is an out variable if an error occurs.
-template <typename IntTy, std::enable_if_t<std::is_unsigned_v<IntTy>, int> = 0>
-static IntTy readULEB128As(DataExtractor &Data, DataExtractor::Cursor &Cur,
-                           Error &ULEBSizeErr) {
-  // Bail out and do not extract data if ULEBSizeErr is already set.
-  if (ULEBSizeErr)
-    return 0;
-  uint64_t Offset = Cur.tell();
-  uint64_t Value = Data.getULEB128(Cur);
-  if (Value > std::numeric_limits<IntTy>::max()) {
-    ULEBSizeErr = createError("ULEB128 value at offset 0x" +
-                              Twine::utohexstr(Offset) + " exceeds UINT" +
-                              Twine(std::numeric_limits<IntTy>::digits) +
-                              "_MAX (0x" + Twine::utohexstr(Value) + ")");
-    return 0;
+/// Address extractor for ELF BB address map sections.
+class ELFBBAddrMapAddressExtractor : public AddressExtractor {
+  bool IsRelocatable;
+  // Maps the offset of each address field in the BB addr map section to the
+  // resolved function address (the relocation addend).
+  DenseMap<uint64_t, uint64_t> FunctionOffsetTranslations;
+
+  ELFBBAddrMapAddressExtractor(
+      const DataExtractor &Data, bool IsRelocatable,
+      DenseMap<uint64_t, uint64_t> FunctionOffsetTranslations)
+      : AddressExtractor(Data), IsRelocatable(IsRelocatable),
+        FunctionOffsetTranslations(std::move(FunctionOffsetTranslations)) {}
+
+public:
+  template <typename ELFT>
+  static Expected<ELFBBAddrMapAddressExtractor>
+  create(const DataExtractor &Data, const ELFFile<ELFT> &EF,
+         const typename ELFFile<ELFT>::Elf_Shdr &Sec,
+         const typename ELFFile<ELFT>::Elf_Shdr *RelaSec) {
+    bool IsRelocatable = EF.getHeader().e_type == ELF::ET_REL;
+
+    // Build relocation offset-to-addend map.
+    DenseMap<uint64_t, uint64_t> FunctionOffsetTranslations;
+    if (IsRelocatable && RelaSec) {
+      assert(RelaSec &&
+             "Can't read a SHT_LLVM_BB_ADDR_MAP section in a relocatable "
+             "object file without providing a relocation section.");
+      if (RelaSec->sh_type == ELF::SHT_CREL) {
+        Expected<typename ELFFile<ELFT>::RelsOrRelas> Relas =
+            EF.crels(*RelaSec);
+        if (!Relas)
+          return createError("unable to read CREL relocations for section " +
+                             describe(EF, Sec) + ": " +
+                             toString(Relas.takeError()));
+        for (typename ELFFile<ELFT>::Elf_Rela Rela : std::get<1>(*Relas))
+          FunctionOffsetTranslations[Rela.r_offset] = Rela.r_addend;
+      } else {
+        Expected<typename ELFFile<ELFT>::Elf_Rela_Range> Relas =
+            EF.relas(*RelaSec);
+        if (!Relas)
+          return createError("unable to read relocations for section " +
+                             describe(EF, Sec) + ": " +
+                             toString(Relas.takeError()));
+        for (typename ELFFile<ELFT>::Elf_Rela Rela : *Relas)
+          FunctionOffsetTranslations[Rela.r_offset] = Rela.r_addend;
+      }
+    }
+
+    return ELFBBAddrMapAddressExtractor(Data, IsRelocatable,
+                                        std::move(FunctionOffsetTranslations));
   }
-  return static_cast<IntTy>(Value);
-}
+
+  Expected<uint64_t> extractAddress(DataExtractor::Cursor &Cur) override {
+    uint64_t Offset = Cur.tell();
+    Expected<uint64_t> AddressOrErr = AddressExtractor::extractAddress(Cur);
+    if (!AddressOrErr)
+      return AddressOrErr.takeError();
+    if (!IsRelocatable)
+      return *AddressOrErr;
+    assert(*AddressOrErr == 0);
----------------
HaohaiWen wrote:

assert removed.

https://github.com/llvm/llvm-project/pull/188435


More information about the llvm-commits mailing list