[llvm] [DWARFYAML] Implement debug_names support (PR #79666)

James Henderson via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 7 00:51:47 PST 2024


================
@@ -691,6 +691,191 @@ Error DWARFYAML::emitDebugStrOffsets(raw_ostream &OS, const Data &DI) {
   return Error::success();
 }
 
+namespace {
+/// Emits the header for a DebugNames section.
+void emitDebugNamesHeader(raw_ostream &OS, bool IsLittleEndian,
+                          uint32_t NameCount, uint32_t AbbrevSize,
+                          uint32_t CombinedSizeOtherParts) {
+  StringRef AugmentationString = "LLVM0700";
+  auto TotalSize = CombinedSizeOtherParts + 5 * sizeof(uint32_t) +
+                   2 * sizeof(uint16_t) + sizeof(NameCount) +
+                   sizeof(AbbrevSize) + AugmentationString.size();
+  writeInteger(uint32_t(TotalSize), OS, IsLittleEndian); // Unit length
+
+  // Everything below is included in total size.
+  writeInteger(uint16_t(5), OS, IsLittleEndian); // Version
+  writeInteger(uint16_t(0), OS, IsLittleEndian); // Padding
+  writeInteger(uint32_t(1), OS, IsLittleEndian); // Compilation Unit count
+  writeInteger(uint32_t(0), OS, IsLittleEndian); // Local Type Unit count
+  writeInteger(uint32_t(0), OS, IsLittleEndian); // Foreign Type Unit count
+  writeInteger(uint32_t(0), OS, IsLittleEndian); // Bucket count
+  writeInteger(NameCount, OS, IsLittleEndian);
+  writeInteger(AbbrevSize, OS, IsLittleEndian);
+  writeInteger(uint32_t(AugmentationString.size()), OS, IsLittleEndian);
+  OS.write(AugmentationString.data(), AugmentationString.size());
+  return;
+}
+
+/// Emits the abbreviations for a DebugNames section.
+std::string
+emitDebugNamesAbbrev(ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {
+  std::string Data;
+  llvm::raw_string_ostream OS(Data);
+  for (const auto &Abbrev : Abbrevs) {
+    encodeULEB128(Abbrev.Code, OS);
+    encodeULEB128(Abbrev.Tag, OS);
+    for (auto [Idx, Form] : Abbrev.Indices) {
+      encodeULEB128(Idx, OS);
+      encodeULEB128(Form, OS);
+    }
+    encodeULEB128(0, OS);
+    encodeULEB128(0, OS);
+  }
+  encodeULEB128(0, OS);
+  return Data;
+}
+
+/// Emits a simple CU offsets list for a DebugNames section containing a single
+/// CU at offset 0.
+std::string emitDebugNamesCUOffsets(bool IsLittleEndian) {
+  std::string Data;
+  llvm::raw_string_ostream OS(Data);
+  writeInteger(uint32_t(0), OS, IsLittleEndian);
+  return Data;
+}
+
+/// Emits the "NameTable" for a DebugNames section; according to the spec, it
+/// consists of two arrays: an array of string offsets, followed immediately by
+/// an array of entry offsets. The string offsets are emitted in the order
+/// provided in `Entries`.
+std::string emitDebugNamesNameTable(
+    bool IsLittleEndian,
+    const std::map<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> &Entries,
+    ArrayRef<uint32_t> EntryPoolOffsets) {
+  assert(Entries.size() == EntryPoolOffsets.size());
+
+  std::string Data;
+  llvm::raw_string_ostream OS(Data);
+
+  for (auto Strp : make_first_range(Entries))
+    writeInteger(Strp, OS, IsLittleEndian);
+  for (auto PoolOffset : EntryPoolOffsets)
+    writeInteger(uint32_t(PoolOffset), OS, IsLittleEndian);
+  return Data;
+}
+
+/// Groups entries based on their name (strp) code and returns a sorted map.
+std::map<uint32_t, std::vector<DWARFYAML::DebugNameEntry>>
+groupEntries(ArrayRef<DWARFYAML::DebugNameEntry> Entries) {
+  std::map<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> Ans;
+  for (const auto &Entry : Entries)
+    Ans[Entry.NameStrp].push_back(Entry);
+  return Ans;
+}
+
+/// Finds the abbreviation whose code is AbbrevCode and returns a list
+/// containing the expected size of all non-zero-length forms.
+Expected<SmallVector<uint8_t>>
+getNonZeroDataSizesFor(uint32_t AbbrevCode,
+                       ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {
+  const auto *AbbrevIt = find_if(Abbrevs, [&](const auto &Abbrev) {
+    return Abbrev.Code.value == AbbrevCode;
+  });
+  if (AbbrevIt == Abbrevs.end())
+    return createStringError(inconvertibleErrorCode(),
+                             "Did not find an Abbreviation for this code");
----------------
jh7370 wrote:

> I understand the desire to support more and more use cases here, but the goal of this patch is to provide the minimal structure required to enable unittests for debug_names (of which there is none today)
> 
> Once this is in, there are lots of extra functionality that can be built on top of it, including the ability to output ill-formed tables.

Yep, I get that, and I'm not suggesting we add anything complex, but at least in some cases it looks to me like it would be just as easy to do a thing (possibly even easier) as to report an error. For example, could you just return an empty vector here, while in the next case, could you just return 0? In cases where there's no clear and simple alternative an error is fine though (as a slight aside, I could be persuaded that in this case no alternative value makes sense).

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


More information about the llvm-commits mailing list