1 //===------ dwarf2yaml.cpp - obj2yaml conversion tool -----------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "Error.h" 11 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 12 #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" 13 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 14 #include "llvm/ObjectYAML/DWARFYAML.h" 15 16 #include <algorithm> 17 18 using namespace llvm; 19 20 void dumpInitialLength(DataExtractor &Data, uint32_t &Offset, 21 DWARFYAML::InitialLength &InitialLength) { 22 InitialLength.TotalLength = Data.getU32(&Offset); 23 if (InitialLength.isDWARF64()) 24 InitialLength.TotalLength64 = Data.getU64(&Offset); 25 } 26 27 void dumpDebugAbbrev(DWARFContext &DCtx, DWARFYAML::Data &Y) { 28 auto AbbrevSetPtr = DCtx.getDebugAbbrev(); 29 if (AbbrevSetPtr) { 30 for (auto AbbrvDeclSet : *AbbrevSetPtr) { 31 for (auto AbbrvDecl : AbbrvDeclSet.second) { 32 DWARFYAML::Abbrev Abbrv; 33 Abbrv.Code = AbbrvDecl.getCode(); 34 Abbrv.Tag = AbbrvDecl.getTag(); 35 Abbrv.Children = AbbrvDecl.hasChildren() ? dwarf::DW_CHILDREN_yes 36 : dwarf::DW_CHILDREN_no; 37 for (auto Attribute : AbbrvDecl.attributes()) { 38 DWARFYAML::AttributeAbbrev AttAbrv; 39 AttAbrv.Attribute = Attribute.Attr; 40 AttAbrv.Form = Attribute.Form; 41 if (AttAbrv.Form == dwarf::DW_FORM_implicit_const) 42 AttAbrv.Value = Attribute.getImplicitConstValue(); 43 Abbrv.Attributes.push_back(AttAbrv); 44 } 45 Y.AbbrevDecls.push_back(Abbrv); 46 } 47 } 48 } 49 } 50 51 void dumpDebugStrings(DWARFContext &DCtx, DWARFYAML::Data &Y) { 52 StringRef RemainingTable = DCtx.getDWARFObj().getStringSection(); 53 while (RemainingTable.size() > 0) { 54 auto SymbolPair = RemainingTable.split('\0'); 55 RemainingTable = SymbolPair.second; 56 Y.DebugStrings.push_back(SymbolPair.first); 57 } 58 } 59 60 void dumpDebugARanges(DWARFContext &DCtx, DWARFYAML::Data &Y) { 61 DataExtractor ArangesData(DCtx.getDWARFObj().getARangeSection(), 62 DCtx.isLittleEndian(), 0); 63 uint32_t Offset = 0; 64 DWARFDebugArangeSet Set; 65 66 while (Set.extract(ArangesData, &Offset)) { 67 DWARFYAML::ARange Range; 68 Range.Length.setLength(Set.getHeader().Length); 69 Range.Version = Set.getHeader().Version; 70 Range.CuOffset = Set.getHeader().CuOffset; 71 Range.AddrSize = Set.getHeader().AddrSize; 72 Range.SegSize = Set.getHeader().SegSize; 73 for (auto Descriptor : Set.descriptors()) { 74 DWARFYAML::ARangeDescriptor Desc; 75 Desc.Address = Descriptor.Address; 76 Desc.Length = Descriptor.Length; 77 Range.Descriptors.push_back(Desc); 78 } 79 Y.ARanges.push_back(Range); 80 } 81 } 82 83 void dumpPubSection(DWARFContext &DCtx, DWARFYAML::PubSection &Y, 84 DWARFSection Section) { 85 DWARFDataExtractor PubSectionData(DCtx.getDWARFObj(), Section, 86 DCtx.isLittleEndian(), 0); 87 uint32_t Offset = 0; 88 dumpInitialLength(PubSectionData, Offset, Y.Length); 89 Y.Version = PubSectionData.getU16(&Offset); 90 Y.UnitOffset = PubSectionData.getU32(&Offset); 91 Y.UnitSize = PubSectionData.getU32(&Offset); 92 while (Offset < Y.Length.getLength()) { 93 DWARFYAML::PubEntry NewEntry; 94 NewEntry.DieOffset = PubSectionData.getU32(&Offset); 95 if (Y.IsGNUStyle) 96 NewEntry.Descriptor = PubSectionData.getU8(&Offset); 97 NewEntry.Name = PubSectionData.getCStr(&Offset); 98 Y.Entries.push_back(NewEntry); 99 } 100 } 101 102 void dumpDebugPubSections(DWARFContext &DCtx, DWARFYAML::Data &Y) { 103 const DWARFObject &D = DCtx.getDWARFObj(); 104 Y.PubNames.IsGNUStyle = false; 105 dumpPubSection(DCtx, Y.PubNames, D.getPubNamesSection()); 106 107 Y.PubTypes.IsGNUStyle = false; 108 dumpPubSection(DCtx, Y.PubTypes, D.getPubTypesSection()); 109 110 Y.GNUPubNames.IsGNUStyle = true; 111 dumpPubSection(DCtx, Y.GNUPubNames, D.getGnuPubNamesSection()); 112 113 Y.GNUPubTypes.IsGNUStyle = true; 114 dumpPubSection(DCtx, Y.GNUPubTypes, D.getGnuPubTypesSection()); 115 } 116 117 void dumpDebugInfo(DWARFContext &DCtx, DWARFYAML::Data &Y) { 118 for (const auto &CU : DCtx.compile_units()) { 119 DWARFYAML::Unit NewUnit; 120 NewUnit.Length.setLength(CU->getLength()); 121 NewUnit.Version = CU->getVersion(); 122 if(NewUnit.Version >= 5) 123 NewUnit.Type = (dwarf::UnitType)CU->getUnitType(); 124 NewUnit.AbbrOffset = CU->getAbbreviations()->getOffset(); 125 NewUnit.AddrSize = CU->getAddressByteSize(); 126 for (auto DIE : CU->dies()) { 127 DWARFYAML::Entry NewEntry; 128 DataExtractor EntryData = CU->getDebugInfoExtractor(); 129 uint32_t offset = DIE.getOffset(); 130 131 assert(EntryData.isValidOffset(offset) && "Invalid DIE Offset"); 132 if (!EntryData.isValidOffset(offset)) 133 continue; 134 135 NewEntry.AbbrCode = EntryData.getULEB128(&offset); 136 137 auto AbbrevDecl = DIE.getAbbreviationDeclarationPtr(); 138 if (AbbrevDecl) { 139 for (const auto &AttrSpec : AbbrevDecl->attributes()) { 140 DWARFYAML::FormValue NewValue; 141 NewValue.Value = 0xDEADBEEFDEADBEEF; 142 DWARFDie DIEWrapper(CU.get(), &DIE); 143 auto FormValue = DIEWrapper.find(AttrSpec.Attr); 144 if (!FormValue) 145 return; 146 auto Form = FormValue.getValue().getForm(); 147 bool indirect = false; 148 do { 149 indirect = false; 150 switch (Form) { 151 case dwarf::DW_FORM_addr: 152 case dwarf::DW_FORM_GNU_addr_index: 153 if (auto Val = FormValue.getValue().getAsAddress()) 154 NewValue.Value = Val.getValue(); 155 break; 156 case dwarf::DW_FORM_ref_addr: 157 case dwarf::DW_FORM_ref1: 158 case dwarf::DW_FORM_ref2: 159 case dwarf::DW_FORM_ref4: 160 case dwarf::DW_FORM_ref8: 161 case dwarf::DW_FORM_ref_udata: 162 case dwarf::DW_FORM_ref_sig8: 163 if (auto Val = FormValue.getValue().getAsReferenceUVal()) 164 NewValue.Value = Val.getValue(); 165 break; 166 case dwarf::DW_FORM_exprloc: 167 case dwarf::DW_FORM_block: 168 case dwarf::DW_FORM_block1: 169 case dwarf::DW_FORM_block2: 170 case dwarf::DW_FORM_block4: 171 if (auto Val = FormValue.getValue().getAsBlock()) { 172 auto BlockData = Val.getValue(); 173 std::copy(BlockData.begin(), BlockData.end(), 174 std::back_inserter(NewValue.BlockData)); 175 } 176 NewValue.Value = NewValue.BlockData.size(); 177 break; 178 case dwarf::DW_FORM_data1: 179 case dwarf::DW_FORM_flag: 180 case dwarf::DW_FORM_data2: 181 case dwarf::DW_FORM_data4: 182 case dwarf::DW_FORM_data8: 183 case dwarf::DW_FORM_sdata: 184 case dwarf::DW_FORM_udata: 185 case dwarf::DW_FORM_ref_sup4: 186 case dwarf::DW_FORM_ref_sup8: 187 if (auto Val = FormValue.getValue().getAsUnsignedConstant()) 188 NewValue.Value = Val.getValue(); 189 break; 190 case dwarf::DW_FORM_string: 191 if (auto Val = FormValue.getValue().getAsCString()) 192 NewValue.CStr = Val.getValue(); 193 break; 194 case dwarf::DW_FORM_indirect: 195 indirect = true; 196 if (auto Val = FormValue.getValue().getAsUnsignedConstant()) { 197 NewValue.Value = Val.getValue(); 198 NewEntry.Values.push_back(NewValue); 199 Form = static_cast<dwarf::Form>(Val.getValue()); 200 } 201 break; 202 case dwarf::DW_FORM_strp: 203 case dwarf::DW_FORM_sec_offset: 204 case dwarf::DW_FORM_GNU_ref_alt: 205 case dwarf::DW_FORM_GNU_strp_alt: 206 case dwarf::DW_FORM_line_strp: 207 case dwarf::DW_FORM_strp_sup: 208 case dwarf::DW_FORM_GNU_str_index: 209 case dwarf::DW_FORM_strx: 210 if (auto Val = FormValue.getValue().getAsCStringOffset()) 211 NewValue.Value = Val.getValue(); 212 break; 213 case dwarf::DW_FORM_flag_present: 214 NewValue.Value = 1; 215 break; 216 default: 217 break; 218 } 219 } while (indirect); 220 NewEntry.Values.push_back(NewValue); 221 } 222 } 223 224 NewUnit.Entries.push_back(NewEntry); 225 } 226 Y.CompileUnits.push_back(NewUnit); 227 } 228 } 229 230 bool dumpFileEntry(DataExtractor &Data, uint32_t &Offset, 231 DWARFYAML::File &File) { 232 File.Name = Data.getCStr(&Offset); 233 if (File.Name.empty()) 234 return false; 235 File.DirIdx = Data.getULEB128(&Offset); 236 File.ModTime = Data.getULEB128(&Offset); 237 File.Length = Data.getULEB128(&Offset); 238 return true; 239 } 240 241 void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) { 242 for (const auto &CU : DCtx.compile_units()) { 243 auto CUDIE = CU->getUnitDIE(); 244 if (!CUDIE) 245 continue; 246 if (auto StmtOffset = 247 dwarf::toSectionOffset(CUDIE.find(dwarf::DW_AT_stmt_list))) { 248 DWARFYAML::LineTable DebugLines; 249 DataExtractor LineData(DCtx.getDWARFObj().getLineSection().Data, 250 DCtx.isLittleEndian(), CU->getAddressByteSize()); 251 uint32_t Offset = *StmtOffset; 252 dumpInitialLength(LineData, Offset, DebugLines.Length); 253 uint64_t LineTableLength = DebugLines.Length.getLength(); 254 uint64_t SizeOfPrologueLength = DebugLines.Length.isDWARF64() ? 8 : 4; 255 DebugLines.Version = LineData.getU16(&Offset); 256 DebugLines.PrologueLength = 257 LineData.getUnsigned(&Offset, SizeOfPrologueLength); 258 const uint64_t EndPrologue = DebugLines.PrologueLength + Offset; 259 260 DebugLines.MinInstLength = LineData.getU8(&Offset); 261 if (DebugLines.Version >= 4) 262 DebugLines.MaxOpsPerInst = LineData.getU8(&Offset); 263 DebugLines.DefaultIsStmt = LineData.getU8(&Offset); 264 DebugLines.LineBase = LineData.getU8(&Offset); 265 DebugLines.LineRange = LineData.getU8(&Offset); 266 DebugLines.OpcodeBase = LineData.getU8(&Offset); 267 268 DebugLines.StandardOpcodeLengths.reserve(DebugLines.OpcodeBase - 1); 269 for (uint8_t i = 1; i < DebugLines.OpcodeBase; ++i) 270 DebugLines.StandardOpcodeLengths.push_back(LineData.getU8(&Offset)); 271 272 while (Offset < EndPrologue) { 273 StringRef Dir = LineData.getCStr(&Offset); 274 if (!Dir.empty()) 275 DebugLines.IncludeDirs.push_back(Dir); 276 else 277 break; 278 } 279 280 while (Offset < EndPrologue) { 281 DWARFYAML::File TmpFile; 282 if (dumpFileEntry(LineData, Offset, TmpFile)) 283 DebugLines.Files.push_back(TmpFile); 284 else 285 break; 286 } 287 288 const uint64_t LineEnd = 289 LineTableLength + *StmtOffset + SizeOfPrologueLength; 290 while (Offset < LineEnd) { 291 DWARFYAML::LineTableOpcode NewOp; 292 NewOp.Opcode = (dwarf::LineNumberOps)LineData.getU8(&Offset); 293 if (NewOp.Opcode == 0) { 294 auto StartExt = Offset; 295 NewOp.ExtLen = LineData.getULEB128(&Offset); 296 NewOp.SubOpcode = 297 (dwarf::LineNumberExtendedOps)LineData.getU8(&Offset); 298 switch (NewOp.SubOpcode) { 299 case dwarf::DW_LNE_set_address: 300 case dwarf::DW_LNE_set_discriminator: 301 NewOp.Data = LineData.getAddress(&Offset); 302 break; 303 case dwarf::DW_LNE_define_file: 304 dumpFileEntry(LineData, Offset, NewOp.FileEntry); 305 break; 306 case dwarf::DW_LNE_end_sequence: 307 break; 308 default: 309 while (Offset < StartExt + NewOp.ExtLen) 310 NewOp.UnknownOpcodeData.push_back(LineData.getU8(&Offset)); 311 } 312 } else if (NewOp.Opcode < DebugLines.OpcodeBase) { 313 switch (NewOp.Opcode) { 314 case dwarf::DW_LNS_copy: 315 case dwarf::DW_LNS_negate_stmt: 316 case dwarf::DW_LNS_set_basic_block: 317 case dwarf::DW_LNS_const_add_pc: 318 case dwarf::DW_LNS_set_prologue_end: 319 case dwarf::DW_LNS_set_epilogue_begin: 320 break; 321 322 case dwarf::DW_LNS_advance_pc: 323 case dwarf::DW_LNS_set_file: 324 case dwarf::DW_LNS_set_column: 325 case dwarf::DW_LNS_set_isa: 326 NewOp.Data = LineData.getULEB128(&Offset); 327 break; 328 329 case dwarf::DW_LNS_advance_line: 330 NewOp.SData = LineData.getSLEB128(&Offset); 331 break; 332 333 case dwarf::DW_LNS_fixed_advance_pc: 334 NewOp.Data = LineData.getU16(&Offset); 335 break; 336 337 default: 338 for (uint8_t i = 0; 339 i < DebugLines.StandardOpcodeLengths[NewOp.Opcode - 1]; ++i) 340 NewOp.StandardOpcodeData.push_back(LineData.getULEB128(&Offset)); 341 } 342 } 343 DebugLines.Opcodes.push_back(NewOp); 344 } 345 Y.DebugLines.push_back(DebugLines); 346 } 347 } 348 } 349 350 std::error_code dwarf2yaml(DWARFContext &DCtx, DWARFYAML::Data &Y) { 351 dumpDebugAbbrev(DCtx, Y); 352 dumpDebugStrings(DCtx, Y); 353 dumpDebugARanges(DCtx, Y); 354 dumpDebugPubSections(DCtx, Y); 355 dumpDebugInfo(DCtx, Y); 356 dumpDebugLines(DCtx, Y); 357 return obj2yaml_error::success; 358 } 359