[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