10b57cec5SDimitry Andric //===- DWARFDebugMacro.h ----------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGMACRO_H
100b57cec5SDimitry Andric #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGMACRO_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
135ffd83dbSDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
145ffd83dbSDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
155ffd83dbSDimitry Andric #include "llvm/Support/Error.h"
160b57cec5SDimitry Andric #include <cstdint>
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric namespace llvm {
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric class raw_ostream;
211db9f3b2SDimitry Andric 
221db9f3b2SDimitry Andric namespace dwarf_linker {
231db9f3b2SDimitry Andric namespace classic {
24bdd1243dSDimitry Andric class DwarfStreamer;
251db9f3b2SDimitry Andric }
261db9f3b2SDimitry Andric } // namespace dwarf_linker
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric class DWARFDebugMacro {
291db9f3b2SDimitry Andric   friend dwarf_linker::classic::DwarfStreamer;
301db9f3b2SDimitry Andric   friend dwarf_linker::parallel::CompileUnit;
31bdd1243dSDimitry Andric 
325ffd83dbSDimitry Andric   /// DWARFv5 section 6.3.1 Macro Information Header.
335ffd83dbSDimitry Andric   enum HeaderFlagMask {
345ffd83dbSDimitry Andric #define HANDLE_MACRO_FLAG(ID, NAME) MACRO_##NAME = ID,
355ffd83dbSDimitry Andric #include "llvm/BinaryFormat/Dwarf.def"
365ffd83dbSDimitry Andric   };
375ffd83dbSDimitry Andric   struct MacroHeader {
385ffd83dbSDimitry Andric     /// Macro version information number.
395ffd83dbSDimitry Andric     uint16_t Version = 0;
405ffd83dbSDimitry Andric 
415ffd83dbSDimitry Andric     /// The bits of the flags field are interpreted as a set of flags, some of
425ffd83dbSDimitry Andric     /// which may indicate that additional fields follow. The following flags,
435ffd83dbSDimitry Andric     /// beginning with the least significant bit, are defined:
445ffd83dbSDimitry Andric     /// offset_size_flag:
455ffd83dbSDimitry Andric     ///   If the offset_size_flag is zero, the header is for a 32-bit DWARF
465ffd83dbSDimitry Andric     ///   format macro section and all offsets are 4 bytes long; if it is one,
475ffd83dbSDimitry Andric     ///   the header is for a 64-bit DWARF format macro section and all offsets
485ffd83dbSDimitry Andric     ///   are 8 bytes long.
495ffd83dbSDimitry Andric     /// debug_line_offset_flag:
505ffd83dbSDimitry Andric     ///   If the debug_line_offset_flag is one, the debug_line_offset field (see
515ffd83dbSDimitry Andric     ///   below) is present. If zero, that field is omitted.
525ffd83dbSDimitry Andric     /// opcode_operands_table_flag:
535ffd83dbSDimitry Andric     ///   If the opcode_operands_table_flag is one, the opcode_operands_table
545ffd83dbSDimitry Andric     ///   field (see below) is present. If zero, that field is omitted.
555ffd83dbSDimitry Andric     uint8_t Flags = 0;
565ffd83dbSDimitry Andric 
575ffd83dbSDimitry Andric     /// debug_line_offset
585ffd83dbSDimitry Andric     ///   An offset in the .debug_line section of the beginning of the line
595ffd83dbSDimitry Andric     ///   number information in the containing compilation unit, encoded as a
605ffd83dbSDimitry Andric     ///   4-byte offset for a 32-bit DWARF format macro section and an 8-byte
615ffd83dbSDimitry Andric     ///   offset for a 64-bit DWARF format macro section.
625ffd83dbSDimitry Andric     uint64_t DebugLineOffset;
635ffd83dbSDimitry Andric 
645ffd83dbSDimitry Andric     /// Print the macro header from the debug_macro section.
655ffd83dbSDimitry Andric     void dumpMacroHeader(raw_ostream &OS) const;
665ffd83dbSDimitry Andric 
675ffd83dbSDimitry Andric     /// Parse the debug_macro header.
685ffd83dbSDimitry Andric     Error parseMacroHeader(DWARFDataExtractor Data, uint64_t *Offset);
695ffd83dbSDimitry Andric 
705ffd83dbSDimitry Andric     /// Get the DWARF format according to the flags.
715ffd83dbSDimitry Andric     dwarf::DwarfFormat getDwarfFormat() const;
725ffd83dbSDimitry Andric 
735ffd83dbSDimitry Andric     /// Get the size of a reference according to the DWARF format.
745ffd83dbSDimitry Andric     uint8_t getOffsetByteSize() const;
755ffd83dbSDimitry Andric   };
765ffd83dbSDimitry Andric 
770b57cec5SDimitry Andric   /// A single macro entry within a macro list.
780b57cec5SDimitry Andric   struct Entry {
790b57cec5SDimitry Andric     /// The type of the macro entry.
800b57cec5SDimitry Andric     uint32_t Type;
810b57cec5SDimitry Andric     union {
820b57cec5SDimitry Andric       /// The source line where the macro is defined.
830b57cec5SDimitry Andric       uint64_t Line;
840b57cec5SDimitry Andric       /// Vendor extension constant value.
850b57cec5SDimitry Andric       uint64_t ExtConstant;
865ffd83dbSDimitry Andric       /// Macro unit import offset.
875ffd83dbSDimitry Andric       uint64_t ImportOffset;
880b57cec5SDimitry Andric     };
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric     union {
910b57cec5SDimitry Andric       /// The string (name, value) of the macro entry.
920b57cec5SDimitry Andric       const char *MacroStr;
930b57cec5SDimitry Andric       // An unsigned integer indicating the identity of the source file.
940b57cec5SDimitry Andric       uint64_t File;
950b57cec5SDimitry Andric       /// Vendor extension string.
960b57cec5SDimitry Andric       const char *ExtStr;
970b57cec5SDimitry Andric     };
980b57cec5SDimitry Andric   };
990b57cec5SDimitry Andric 
1005ffd83dbSDimitry Andric   struct MacroList {
1015ffd83dbSDimitry Andric     // A value 0 in the `Header.Version` field indicates that we're parsing
1025ffd83dbSDimitry Andric     // a macinfo[.dwo] section which doesn't have header itself, hence
1035ffd83dbSDimitry Andric     // for that case other fields in the `Header` are uninitialized.
1045ffd83dbSDimitry Andric     MacroHeader Header;
1055ffd83dbSDimitry Andric     SmallVector<Entry, 4> Macros;
1065ffd83dbSDimitry Andric     uint64_t Offset;
107e8d8bef9SDimitry Andric 
108e8d8bef9SDimitry Andric     /// Whether or not this is a .debug_macro section.
109e8d8bef9SDimitry Andric     bool IsDebugMacro;
1105ffd83dbSDimitry Andric   };
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   /// A list of all the macro entries in the debug_macinfo section.
113480093f4SDimitry Andric   std::vector<MacroList> MacroLists;
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric public:
1160b57cec5SDimitry Andric   DWARFDebugMacro() = default;
1170b57cec5SDimitry Andric 
1185ffd83dbSDimitry Andric   /// Print the macro list found within the debug_macinfo/debug_macro section.
1190b57cec5SDimitry Andric   void dump(raw_ostream &OS) const;
1200b57cec5SDimitry Andric 
parseMacro(DWARFUnitVector::compile_unit_range Units,DataExtractor StringExtractor,DWARFDataExtractor MacroData)121e8d8bef9SDimitry Andric   Error parseMacro(DWARFUnitVector::compile_unit_range Units,
1225ffd83dbSDimitry Andric                    DataExtractor StringExtractor,
1235ffd83dbSDimitry Andric                    DWARFDataExtractor MacroData) {
1245ffd83dbSDimitry Andric     return parseImpl(Units, StringExtractor, MacroData, /*IsMacro=*/true);
1255ffd83dbSDimitry Andric   }
1265ffd83dbSDimitry Andric 
parseMacinfo(DWARFDataExtractor MacroData)1275ffd83dbSDimitry Andric   Error parseMacinfo(DWARFDataExtractor MacroData) {
128bdd1243dSDimitry Andric     return parseImpl(std::nullopt, std::nullopt, MacroData, /*IsMacro=*/false);
1295ffd83dbSDimitry Andric   }
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   /// Return whether the section has any entries.
empty()132480093f4SDimitry Andric   bool empty() const { return MacroLists.empty(); }
1335ffd83dbSDimitry Andric 
hasEntryForOffset(uint64_t Offset)134bdd1243dSDimitry Andric   bool hasEntryForOffset(uint64_t Offset) const {
135bdd1243dSDimitry Andric     for (const MacroList &List : MacroLists)
136bdd1243dSDimitry Andric       if (Offset == List.Offset)
137bdd1243dSDimitry Andric         return true;
138bdd1243dSDimitry Andric 
139bdd1243dSDimitry Andric     return false;
140bdd1243dSDimitry Andric   }
141bdd1243dSDimitry Andric 
1425ffd83dbSDimitry Andric private:
1435ffd83dbSDimitry Andric   /// Parse the debug_macinfo/debug_macro section accessible via the 'MacroData'
1445ffd83dbSDimitry Andric   /// parameter.
145bdd1243dSDimitry Andric   Error parseImpl(std::optional<DWARFUnitVector::compile_unit_range> Units,
146bdd1243dSDimitry Andric                   std::optional<DataExtractor> StringExtractor,
1475ffd83dbSDimitry Andric                   DWARFDataExtractor Data, bool IsMacro);
1480b57cec5SDimitry Andric };
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric } // end namespace llvm
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric #endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGMACRO_H
153