1 //===- DWARFEmitter - Convert YAML to DWARF binary data -------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// The DWARF component of yaml2obj. Provided as library code for tests. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/ObjectYAML/DWARFEmitter.h" 15 #include "llvm/ADT/ArrayRef.h" 16 #include "llvm/ADT/StringMap.h" 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/ADT/StringSwitch.h" 19 #include "llvm/BinaryFormat/Dwarf.h" 20 #include "llvm/ObjectYAML/DWARFYAML.h" 21 #include "llvm/Support/Errc.h" 22 #include "llvm/Support/Error.h" 23 #include "llvm/Support/LEB128.h" 24 #include "llvm/Support/MathExtras.h" 25 #include "llvm/Support/MemoryBuffer.h" 26 #include "llvm/Support/SourceMgr.h" 27 #include "llvm/Support/SwapByteOrder.h" 28 #include "llvm/Support/YAMLTraits.h" 29 #include "llvm/Support/raw_ostream.h" 30 #include "llvm/TargetParser/Host.h" 31 #include <cassert> 32 #include <cstddef> 33 #include <cstdint> 34 #include <memory> 35 #include <optional> 36 #include <string> 37 #include <vector> 38 39 using namespace llvm; 40 41 template <typename T> 42 static void writeInteger(T Integer, raw_ostream &OS, bool IsLittleEndian) { 43 if (IsLittleEndian != sys::IsLittleEndianHost) 44 sys::swapByteOrder(Integer); 45 OS.write(reinterpret_cast<char *>(&Integer), sizeof(T)); 46 } 47 48 static Error writeVariableSizedInteger(uint64_t Integer, size_t Size, 49 raw_ostream &OS, bool IsLittleEndian) { 50 if (8 == Size) 51 writeInteger((uint64_t)Integer, OS, IsLittleEndian); 52 else if (4 == Size) 53 writeInteger((uint32_t)Integer, OS, IsLittleEndian); 54 else if (2 == Size) 55 writeInteger((uint16_t)Integer, OS, IsLittleEndian); 56 else if (1 == Size) 57 writeInteger((uint8_t)Integer, OS, IsLittleEndian); 58 else 59 return createStringError(errc::not_supported, 60 "invalid integer write size: %zu", Size); 61 62 return Error::success(); 63 } 64 65 static void ZeroFillBytes(raw_ostream &OS, size_t Size) { 66 std::vector<uint8_t> FillData(Size, 0); 67 OS.write(reinterpret_cast<char *>(FillData.data()), Size); 68 } 69 70 static void writeInitialLength(const dwarf::DwarfFormat Format, 71 const uint64_t Length, raw_ostream &OS, 72 bool IsLittleEndian) { 73 bool IsDWARF64 = Format == dwarf::DWARF64; 74 if (IsDWARF64) 75 cantFail(writeVariableSizedInteger(dwarf::DW_LENGTH_DWARF64, 4, OS, 76 IsLittleEndian)); 77 cantFail( 78 writeVariableSizedInteger(Length, IsDWARF64 ? 8 : 4, OS, IsLittleEndian)); 79 } 80 81 static void writeDWARFOffset(uint64_t Offset, dwarf::DwarfFormat Format, 82 raw_ostream &OS, bool IsLittleEndian) { 83 cantFail(writeVariableSizedInteger(Offset, Format == dwarf::DWARF64 ? 8 : 4, 84 OS, IsLittleEndian)); 85 } 86 87 Error DWARFYAML::emitDebugStr(raw_ostream &OS, const DWARFYAML::Data &DI) { 88 for (StringRef Str : *DI.DebugStrings) { 89 OS.write(Str.data(), Str.size()); 90 OS.write('\0'); 91 } 92 93 return Error::success(); 94 } 95 96 StringRef DWARFYAML::Data::getAbbrevTableContentByIndex(uint64_t Index) const { 97 assert(Index < DebugAbbrev.size() && 98 "Index should be less than the size of DebugAbbrev array"); 99 auto It = AbbrevTableContents.find(Index); 100 if (It != AbbrevTableContents.cend()) 101 return It->second; 102 103 std::string AbbrevTableBuffer; 104 raw_string_ostream OS(AbbrevTableBuffer); 105 106 uint64_t AbbrevCode = 0; 107 for (const DWARFYAML::Abbrev &AbbrevDecl : DebugAbbrev[Index].Table) { 108 AbbrevCode = AbbrevDecl.Code ? (uint64_t)*AbbrevDecl.Code : AbbrevCode + 1; 109 encodeULEB128(AbbrevCode, OS); 110 encodeULEB128(AbbrevDecl.Tag, OS); 111 OS.write(AbbrevDecl.Children); 112 for (const auto &Attr : AbbrevDecl.Attributes) { 113 encodeULEB128(Attr.Attribute, OS); 114 encodeULEB128(Attr.Form, OS); 115 if (Attr.Form == dwarf::DW_FORM_implicit_const) 116 encodeSLEB128(Attr.Value, OS); 117 } 118 encodeULEB128(0, OS); 119 encodeULEB128(0, OS); 120 } 121 122 // The abbreviations for a given compilation unit end with an entry 123 // consisting of a 0 byte for the abbreviation code. 124 OS.write_zeros(1); 125 126 AbbrevTableContents.insert({Index, AbbrevTableBuffer}); 127 128 return AbbrevTableContents[Index]; 129 } 130 131 Error DWARFYAML::emitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) { 132 for (uint64_t I = 0; I < DI.DebugAbbrev.size(); ++I) { 133 StringRef AbbrevTableContent = DI.getAbbrevTableContentByIndex(I); 134 OS.write(AbbrevTableContent.data(), AbbrevTableContent.size()); 135 } 136 137 return Error::success(); 138 } 139 140 Error DWARFYAML::emitDebugAranges(raw_ostream &OS, const DWARFYAML::Data &DI) { 141 assert(DI.DebugAranges && "unexpected emitDebugAranges() call"); 142 for (const auto &Range : *DI.DebugAranges) { 143 uint8_t AddrSize; 144 if (Range.AddrSize) 145 AddrSize = *Range.AddrSize; 146 else 147 AddrSize = DI.Is64BitAddrSize ? 8 : 4; 148 149 uint64_t Length = 4; // sizeof(version) 2 + sizeof(address_size) 1 + 150 // sizeof(segment_selector_size) 1 151 Length += 152 Range.Format == dwarf::DWARF64 ? 8 : 4; // sizeof(debug_info_offset) 153 154 const uint64_t HeaderLength = 155 Length + (Range.Format == dwarf::DWARF64 156 ? 12 157 : 4); // sizeof(unit_header) = 12 (DWARF64) or 4 (DWARF32) 158 const uint64_t PaddedHeaderLength = alignTo(HeaderLength, AddrSize * 2); 159 160 if (Range.Length) { 161 Length = *Range.Length; 162 } else { 163 Length += PaddedHeaderLength - HeaderLength; 164 Length += AddrSize * 2 * (Range.Descriptors.size() + 1); 165 } 166 167 writeInitialLength(Range.Format, Length, OS, DI.IsLittleEndian); 168 writeInteger((uint16_t)Range.Version, OS, DI.IsLittleEndian); 169 writeDWARFOffset(Range.CuOffset, Range.Format, OS, DI.IsLittleEndian); 170 writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian); 171 writeInteger((uint8_t)Range.SegSize, OS, DI.IsLittleEndian); 172 ZeroFillBytes(OS, PaddedHeaderLength - HeaderLength); 173 174 for (const auto &Descriptor : Range.Descriptors) { 175 if (Error Err = writeVariableSizedInteger(Descriptor.Address, AddrSize, 176 OS, DI.IsLittleEndian)) 177 return createStringError(errc::not_supported, 178 "unable to write debug_aranges address: %s", 179 toString(std::move(Err)).c_str()); 180 cantFail(writeVariableSizedInteger(Descriptor.Length, AddrSize, OS, 181 DI.IsLittleEndian)); 182 } 183 ZeroFillBytes(OS, AddrSize * 2); 184 } 185 186 return Error::success(); 187 } 188 189 Error DWARFYAML::emitDebugRanges(raw_ostream &OS, const DWARFYAML::Data &DI) { 190 const size_t RangesOffset = OS.tell(); 191 uint64_t EntryIndex = 0; 192 for (const auto &DebugRanges : *DI.DebugRanges) { 193 const size_t CurrOffset = OS.tell() - RangesOffset; 194 if (DebugRanges.Offset && (uint64_t)*DebugRanges.Offset < CurrOffset) 195 return createStringError(errc::invalid_argument, 196 "'Offset' for 'debug_ranges' with index " + 197 Twine(EntryIndex) + 198 " must be greater than or equal to the " 199 "number of bytes written already (0x" + 200 Twine::utohexstr(CurrOffset) + ")"); 201 if (DebugRanges.Offset) 202 ZeroFillBytes(OS, *DebugRanges.Offset - CurrOffset); 203 204 uint8_t AddrSize; 205 if (DebugRanges.AddrSize) 206 AddrSize = *DebugRanges.AddrSize; 207 else 208 AddrSize = DI.Is64BitAddrSize ? 8 : 4; 209 for (const auto &Entry : DebugRanges.Entries) { 210 if (Error Err = writeVariableSizedInteger(Entry.LowOffset, AddrSize, OS, 211 DI.IsLittleEndian)) 212 return createStringError( 213 errc::not_supported, 214 "unable to write debug_ranges address offset: %s", 215 toString(std::move(Err)).c_str()); 216 cantFail(writeVariableSizedInteger(Entry.HighOffset, AddrSize, OS, 217 DI.IsLittleEndian)); 218 } 219 ZeroFillBytes(OS, AddrSize * 2); 220 ++EntryIndex; 221 } 222 223 return Error::success(); 224 } 225 226 static Error emitPubSection(raw_ostream &OS, const DWARFYAML::PubSection &Sect, 227 bool IsLittleEndian, bool IsGNUPubSec = false) { 228 writeInitialLength(Sect.Format, Sect.Length, OS, IsLittleEndian); 229 writeInteger((uint16_t)Sect.Version, OS, IsLittleEndian); 230 writeInteger((uint32_t)Sect.UnitOffset, OS, IsLittleEndian); 231 writeInteger((uint32_t)Sect.UnitSize, OS, IsLittleEndian); 232 for (const auto &Entry : Sect.Entries) { 233 writeInteger((uint32_t)Entry.DieOffset, OS, IsLittleEndian); 234 if (IsGNUPubSec) 235 writeInteger((uint8_t)Entry.Descriptor, OS, IsLittleEndian); 236 OS.write(Entry.Name.data(), Entry.Name.size()); 237 OS.write('\0'); 238 } 239 return Error::success(); 240 } 241 242 Error DWARFYAML::emitDebugPubnames(raw_ostream &OS, const Data &DI) { 243 assert(DI.PubNames && "unexpected emitDebugPubnames() call"); 244 return emitPubSection(OS, *DI.PubNames, DI.IsLittleEndian); 245 } 246 247 Error DWARFYAML::emitDebugPubtypes(raw_ostream &OS, const Data &DI) { 248 assert(DI.PubTypes && "unexpected emitDebugPubtypes() call"); 249 return emitPubSection(OS, *DI.PubTypes, DI.IsLittleEndian); 250 } 251 252 Error DWARFYAML::emitDebugGNUPubnames(raw_ostream &OS, const Data &DI) { 253 assert(DI.GNUPubNames && "unexpected emitDebugGNUPubnames() call"); 254 return emitPubSection(OS, *DI.GNUPubNames, DI.IsLittleEndian, 255 /*IsGNUStyle=*/true); 256 } 257 258 Error DWARFYAML::emitDebugGNUPubtypes(raw_ostream &OS, const Data &DI) { 259 assert(DI.GNUPubTypes && "unexpected emitDebugGNUPubtypes() call"); 260 return emitPubSection(OS, *DI.GNUPubTypes, DI.IsLittleEndian, 261 /*IsGNUStyle=*/true); 262 } 263 264 static Expected<uint64_t> writeDIE(const DWARFYAML::Data &DI, uint64_t CUIndex, 265 uint64_t AbbrevTableID, 266 const dwarf::FormParams &Params, 267 const DWARFYAML::Entry &Entry, 268 raw_ostream &OS, bool IsLittleEndian) { 269 uint64_t EntryBegin = OS.tell(); 270 encodeULEB128(Entry.AbbrCode, OS); 271 uint32_t AbbrCode = Entry.AbbrCode; 272 if (AbbrCode == 0 || Entry.Values.empty()) 273 return OS.tell() - EntryBegin; 274 275 Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr = 276 DI.getAbbrevTableInfoByID(AbbrevTableID); 277 if (!AbbrevTableInfoOrErr) 278 return createStringError(errc::invalid_argument, 279 toString(AbbrevTableInfoOrErr.takeError()) + 280 " for compilation unit with index " + 281 utostr(CUIndex)); 282 283 ArrayRef<DWARFYAML::Abbrev> AbbrevDecls( 284 DI.DebugAbbrev[AbbrevTableInfoOrErr->Index].Table); 285 286 if (AbbrCode > AbbrevDecls.size()) 287 return createStringError( 288 errc::invalid_argument, 289 "abbrev code must be less than or equal to the number of " 290 "entries in abbreviation table"); 291 const DWARFYAML::Abbrev &Abbrev = AbbrevDecls[AbbrCode - 1]; 292 auto FormVal = Entry.Values.begin(); 293 auto AbbrForm = Abbrev.Attributes.begin(); 294 for (; FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end(); 295 ++FormVal, ++AbbrForm) { 296 dwarf::Form Form = AbbrForm->Form; 297 bool Indirect; 298 do { 299 Indirect = false; 300 switch (Form) { 301 case dwarf::DW_FORM_addr: 302 // TODO: Test this error. 303 if (Error Err = writeVariableSizedInteger( 304 FormVal->Value, Params.AddrSize, OS, IsLittleEndian)) 305 return std::move(Err); 306 break; 307 case dwarf::DW_FORM_ref_addr: 308 // TODO: Test this error. 309 if (Error Err = writeVariableSizedInteger(FormVal->Value, 310 Params.getRefAddrByteSize(), 311 OS, IsLittleEndian)) 312 return std::move(Err); 313 break; 314 case dwarf::DW_FORM_exprloc: 315 case dwarf::DW_FORM_block: 316 encodeULEB128(FormVal->BlockData.size(), OS); 317 OS.write((const char *)FormVal->BlockData.data(), 318 FormVal->BlockData.size()); 319 break; 320 case dwarf::DW_FORM_block1: { 321 writeInteger((uint8_t)FormVal->BlockData.size(), OS, IsLittleEndian); 322 OS.write((const char *)FormVal->BlockData.data(), 323 FormVal->BlockData.size()); 324 break; 325 } 326 case dwarf::DW_FORM_block2: { 327 writeInteger((uint16_t)FormVal->BlockData.size(), OS, IsLittleEndian); 328 OS.write((const char *)FormVal->BlockData.data(), 329 FormVal->BlockData.size()); 330 break; 331 } 332 case dwarf::DW_FORM_block4: { 333 writeInteger((uint32_t)FormVal->BlockData.size(), OS, IsLittleEndian); 334 OS.write((const char *)FormVal->BlockData.data(), 335 FormVal->BlockData.size()); 336 break; 337 } 338 case dwarf::DW_FORM_strx: 339 case dwarf::DW_FORM_addrx: 340 case dwarf::DW_FORM_rnglistx: 341 case dwarf::DW_FORM_loclistx: 342 case dwarf::DW_FORM_udata: 343 case dwarf::DW_FORM_ref_udata: 344 case dwarf::DW_FORM_GNU_addr_index: 345 case dwarf::DW_FORM_GNU_str_index: 346 encodeULEB128(FormVal->Value, OS); 347 break; 348 case dwarf::DW_FORM_data1: 349 case dwarf::DW_FORM_ref1: 350 case dwarf::DW_FORM_flag: 351 case dwarf::DW_FORM_strx1: 352 case dwarf::DW_FORM_addrx1: 353 writeInteger((uint8_t)FormVal->Value, OS, IsLittleEndian); 354 break; 355 case dwarf::DW_FORM_data2: 356 case dwarf::DW_FORM_ref2: 357 case dwarf::DW_FORM_strx2: 358 case dwarf::DW_FORM_addrx2: 359 writeInteger((uint16_t)FormVal->Value, OS, IsLittleEndian); 360 break; 361 case dwarf::DW_FORM_data4: 362 case dwarf::DW_FORM_ref4: 363 case dwarf::DW_FORM_ref_sup4: 364 case dwarf::DW_FORM_strx4: 365 case dwarf::DW_FORM_addrx4: 366 writeInteger((uint32_t)FormVal->Value, OS, IsLittleEndian); 367 break; 368 case dwarf::DW_FORM_data8: 369 case dwarf::DW_FORM_ref8: 370 case dwarf::DW_FORM_ref_sup8: 371 case dwarf::DW_FORM_ref_sig8: 372 writeInteger((uint64_t)FormVal->Value, OS, IsLittleEndian); 373 break; 374 case dwarf::DW_FORM_sdata: 375 encodeSLEB128(FormVal->Value, OS); 376 break; 377 case dwarf::DW_FORM_string: 378 OS.write(FormVal->CStr.data(), FormVal->CStr.size()); 379 OS.write('\0'); 380 break; 381 case dwarf::DW_FORM_indirect: 382 encodeULEB128(FormVal->Value, OS); 383 Indirect = true; 384 Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value); 385 ++FormVal; 386 break; 387 case dwarf::DW_FORM_strp: 388 case dwarf::DW_FORM_sec_offset: 389 case dwarf::DW_FORM_GNU_ref_alt: 390 case dwarf::DW_FORM_GNU_strp_alt: 391 case dwarf::DW_FORM_line_strp: 392 case dwarf::DW_FORM_strp_sup: 393 cantFail(writeVariableSizedInteger(FormVal->Value, 394 Params.getDwarfOffsetByteSize(), OS, 395 IsLittleEndian)); 396 break; 397 default: 398 break; 399 } 400 } while (Indirect); 401 } 402 403 return OS.tell() - EntryBegin; 404 } 405 406 Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) { 407 for (uint64_t I = 0; I < DI.Units.size(); ++I) { 408 const DWARFYAML::Unit &Unit = DI.Units[I]; 409 uint8_t AddrSize; 410 if (Unit.AddrSize) 411 AddrSize = *Unit.AddrSize; 412 else 413 AddrSize = DI.Is64BitAddrSize ? 8 : 4; 414 dwarf::FormParams Params = {Unit.Version, AddrSize, Unit.Format}; 415 uint64_t Length = 3; // sizeof(version) + sizeof(address_size) 416 Length += Params.getDwarfOffsetByteSize(); // sizeof(debug_abbrev_offset) 417 if (Unit.Version >= 5) { 418 ++Length; // sizeof(unit_type) 419 switch (Unit.Type) { 420 case dwarf::DW_UT_compile: 421 case dwarf::DW_UT_partial: 422 default: 423 break; 424 case dwarf::DW_UT_type: 425 case dwarf::DW_UT_split_type: 426 // sizeof(type_signature) + sizeof(type_offset) 427 Length += 8 + Params.getDwarfOffsetByteSize(); 428 break; 429 case dwarf::DW_UT_skeleton: 430 case dwarf::DW_UT_split_compile: 431 Length += 8; // sizeof(dwo_id) 432 } 433 } 434 435 // Since the length of the current compilation unit is undetermined yet, we 436 // firstly write the content of the compilation unit to a buffer to 437 // calculate it and then serialize the buffer content to the actual output 438 // stream. 439 std::string EntryBuffer; 440 raw_string_ostream EntryBufferOS(EntryBuffer); 441 442 uint64_t AbbrevTableID = Unit.AbbrevTableID.value_or(I); 443 for (const DWARFYAML::Entry &Entry : Unit.Entries) { 444 if (Expected<uint64_t> EntryLength = 445 writeDIE(DI, I, AbbrevTableID, Params, Entry, EntryBufferOS, 446 DI.IsLittleEndian)) 447 Length += *EntryLength; 448 else 449 return EntryLength.takeError(); 450 } 451 452 // If the length is specified in the YAML description, we use it instead of 453 // the actual length. 454 if (Unit.Length) 455 Length = *Unit.Length; 456 457 writeInitialLength(Unit.Format, Length, OS, DI.IsLittleEndian); 458 writeInteger((uint16_t)Unit.Version, OS, DI.IsLittleEndian); 459 460 uint64_t AbbrevTableOffset = 0; 461 if (Unit.AbbrOffset) { 462 AbbrevTableOffset = *Unit.AbbrOffset; 463 } else { 464 if (Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr = 465 DI.getAbbrevTableInfoByID(AbbrevTableID)) { 466 AbbrevTableOffset = AbbrevTableInfoOrErr->Offset; 467 } else { 468 // The current compilation unit may not have DIEs and it will not be 469 // able to find the associated abbrev table. We consume the error and 470 // assign 0 to the debug_abbrev_offset in such circumstances. 471 consumeError(AbbrevTableInfoOrErr.takeError()); 472 } 473 } 474 475 if (Unit.Version >= 5) { 476 writeInteger((uint8_t)Unit.Type, OS, DI.IsLittleEndian); 477 writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian); 478 writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian); 479 switch (Unit.Type) { 480 case dwarf::DW_UT_compile: 481 case dwarf::DW_UT_partial: 482 default: 483 break; 484 case dwarf::DW_UT_type: 485 case dwarf::DW_UT_split_type: 486 writeInteger(Unit.TypeSignatureOrDwoID, OS, DI.IsLittleEndian); 487 writeDWARFOffset(Unit.TypeOffset, Unit.Format, OS, DI.IsLittleEndian); 488 break; 489 case dwarf::DW_UT_skeleton: 490 case dwarf::DW_UT_split_compile: 491 writeInteger(Unit.TypeSignatureOrDwoID, OS, DI.IsLittleEndian); 492 break; 493 } 494 } else { 495 writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian); 496 writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian); 497 } 498 499 OS.write(EntryBuffer.data(), EntryBuffer.size()); 500 } 501 502 return Error::success(); 503 } 504 505 static void emitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) { 506 OS.write(File.Name.data(), File.Name.size()); 507 OS.write('\0'); 508 encodeULEB128(File.DirIdx, OS); 509 encodeULEB128(File.ModTime, OS); 510 encodeULEB128(File.Length, OS); 511 } 512 513 static void writeExtendedOpcode(const DWARFYAML::LineTableOpcode &Op, 514 uint8_t AddrSize, bool IsLittleEndian, 515 raw_ostream &OS) { 516 // The first byte of extended opcodes is a zero byte. The next bytes are an 517 // ULEB128 integer giving the number of bytes in the instruction itself (does 518 // not include the first zero byte or the size). We serialize the instruction 519 // itself into the OpBuffer and then write the size of the buffer and the 520 // buffer to the real output stream. 521 std::string OpBuffer; 522 raw_string_ostream OpBufferOS(OpBuffer); 523 writeInteger((uint8_t)Op.SubOpcode, OpBufferOS, IsLittleEndian); 524 switch (Op.SubOpcode) { 525 case dwarf::DW_LNE_set_address: 526 cantFail(writeVariableSizedInteger(Op.Data, AddrSize, OpBufferOS, 527 IsLittleEndian)); 528 break; 529 case dwarf::DW_LNE_define_file: 530 emitFileEntry(OpBufferOS, Op.FileEntry); 531 break; 532 case dwarf::DW_LNE_set_discriminator: 533 encodeULEB128(Op.Data, OpBufferOS); 534 break; 535 case dwarf::DW_LNE_end_sequence: 536 break; 537 default: 538 for (auto OpByte : Op.UnknownOpcodeData) 539 writeInteger((uint8_t)OpByte, OpBufferOS, IsLittleEndian); 540 } 541 uint64_t ExtLen = Op.ExtLen.value_or(OpBuffer.size()); 542 encodeULEB128(ExtLen, OS); 543 OS.write(OpBuffer.data(), OpBuffer.size()); 544 } 545 546 static void writeLineTableOpcode(const DWARFYAML::LineTableOpcode &Op, 547 uint8_t OpcodeBase, uint8_t AddrSize, 548 raw_ostream &OS, bool IsLittleEndian) { 549 writeInteger((uint8_t)Op.Opcode, OS, IsLittleEndian); 550 if (Op.Opcode == 0) { 551 writeExtendedOpcode(Op, AddrSize, IsLittleEndian, OS); 552 } else if (Op.Opcode < OpcodeBase) { 553 switch (Op.Opcode) { 554 case dwarf::DW_LNS_copy: 555 case dwarf::DW_LNS_negate_stmt: 556 case dwarf::DW_LNS_set_basic_block: 557 case dwarf::DW_LNS_const_add_pc: 558 case dwarf::DW_LNS_set_prologue_end: 559 case dwarf::DW_LNS_set_epilogue_begin: 560 break; 561 562 case dwarf::DW_LNS_advance_pc: 563 case dwarf::DW_LNS_set_file: 564 case dwarf::DW_LNS_set_column: 565 case dwarf::DW_LNS_set_isa: 566 encodeULEB128(Op.Data, OS); 567 break; 568 569 case dwarf::DW_LNS_advance_line: 570 encodeSLEB128(Op.SData, OS); 571 break; 572 573 case dwarf::DW_LNS_fixed_advance_pc: 574 writeInteger((uint16_t)Op.Data, OS, IsLittleEndian); 575 break; 576 577 default: 578 for (auto OpData : Op.StandardOpcodeData) { 579 encodeULEB128(OpData, OS); 580 } 581 } 582 } 583 } 584 585 static std::vector<uint8_t> 586 getStandardOpcodeLengths(uint16_t Version, std::optional<uint8_t> OpcodeBase) { 587 // If the opcode_base field isn't specified, we returns the 588 // standard_opcode_lengths array according to the version by default. 589 std::vector<uint8_t> StandardOpcodeLengths{0, 1, 1, 1, 1, 0, 590 0, 0, 1, 0, 0, 1}; 591 if (Version == 2) { 592 // DWARF v2 uses the same first 9 standard opcodes as v3-5. 593 StandardOpcodeLengths.resize(9); 594 } else if (OpcodeBase) { 595 StandardOpcodeLengths.resize(*OpcodeBase > 0 ? *OpcodeBase - 1 : 0, 0); 596 } 597 return StandardOpcodeLengths; 598 } 599 600 Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) { 601 for (const DWARFYAML::LineTable &LineTable : DI.DebugLines) { 602 // Buffer holds the bytes following the header_length (or prologue_length in 603 // DWARFv2) field to the end of the line number program itself. 604 std::string Buffer; 605 raw_string_ostream BufferOS(Buffer); 606 607 writeInteger(LineTable.MinInstLength, BufferOS, DI.IsLittleEndian); 608 // TODO: Add support for emitting DWARFv5 line table. 609 if (LineTable.Version >= 4) 610 writeInteger(LineTable.MaxOpsPerInst, BufferOS, DI.IsLittleEndian); 611 writeInteger(LineTable.DefaultIsStmt, BufferOS, DI.IsLittleEndian); 612 writeInteger(LineTable.LineBase, BufferOS, DI.IsLittleEndian); 613 writeInteger(LineTable.LineRange, BufferOS, DI.IsLittleEndian); 614 615 std::vector<uint8_t> StandardOpcodeLengths = 616 LineTable.StandardOpcodeLengths.value_or( 617 getStandardOpcodeLengths(LineTable.Version, LineTable.OpcodeBase)); 618 uint8_t OpcodeBase = LineTable.OpcodeBase 619 ? *LineTable.OpcodeBase 620 : StandardOpcodeLengths.size() + 1; 621 writeInteger(OpcodeBase, BufferOS, DI.IsLittleEndian); 622 for (uint8_t OpcodeLength : StandardOpcodeLengths) 623 writeInteger(OpcodeLength, BufferOS, DI.IsLittleEndian); 624 625 for (StringRef IncludeDir : LineTable.IncludeDirs) { 626 BufferOS.write(IncludeDir.data(), IncludeDir.size()); 627 BufferOS.write('\0'); 628 } 629 BufferOS.write('\0'); 630 631 for (const DWARFYAML::File &File : LineTable.Files) 632 emitFileEntry(BufferOS, File); 633 BufferOS.write('\0'); 634 635 uint64_t HeaderLength = 636 LineTable.PrologueLength ? *LineTable.PrologueLength : Buffer.size(); 637 638 for (const DWARFYAML::LineTableOpcode &Op : LineTable.Opcodes) 639 writeLineTableOpcode(Op, OpcodeBase, DI.Is64BitAddrSize ? 8 : 4, BufferOS, 640 DI.IsLittleEndian); 641 642 uint64_t Length; 643 if (LineTable.Length) { 644 Length = *LineTable.Length; 645 } else { 646 Length = 2; // sizeof(version) 647 Length += 648 (LineTable.Format == dwarf::DWARF64 ? 8 : 4); // sizeof(header_length) 649 Length += Buffer.size(); 650 } 651 652 writeInitialLength(LineTable.Format, Length, OS, DI.IsLittleEndian); 653 writeInteger(LineTable.Version, OS, DI.IsLittleEndian); 654 writeDWARFOffset(HeaderLength, LineTable.Format, OS, DI.IsLittleEndian); 655 OS.write(Buffer.data(), Buffer.size()); 656 } 657 658 return Error::success(); 659 } 660 661 Error DWARFYAML::emitDebugAddr(raw_ostream &OS, const Data &DI) { 662 for (const AddrTableEntry &TableEntry : *DI.DebugAddr) { 663 uint8_t AddrSize; 664 if (TableEntry.AddrSize) 665 AddrSize = *TableEntry.AddrSize; 666 else 667 AddrSize = DI.Is64BitAddrSize ? 8 : 4; 668 669 uint64_t Length; 670 if (TableEntry.Length) 671 Length = (uint64_t)*TableEntry.Length; 672 else 673 // 2 (version) + 1 (address_size) + 1 (segment_selector_size) = 4 674 Length = 4 + (AddrSize + TableEntry.SegSelectorSize) * 675 TableEntry.SegAddrPairs.size(); 676 677 writeInitialLength(TableEntry.Format, Length, OS, DI.IsLittleEndian); 678 writeInteger((uint16_t)TableEntry.Version, OS, DI.IsLittleEndian); 679 writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian); 680 writeInteger((uint8_t)TableEntry.SegSelectorSize, OS, DI.IsLittleEndian); 681 682 for (const SegAddrPair &Pair : TableEntry.SegAddrPairs) { 683 if (TableEntry.SegSelectorSize != yaml::Hex8{0}) 684 if (Error Err = writeVariableSizedInteger(Pair.Segment, 685 TableEntry.SegSelectorSize, 686 OS, DI.IsLittleEndian)) 687 return createStringError(errc::not_supported, 688 "unable to write debug_addr segment: %s", 689 toString(std::move(Err)).c_str()); 690 if (AddrSize != 0) 691 if (Error Err = writeVariableSizedInteger(Pair.Address, AddrSize, OS, 692 DI.IsLittleEndian)) 693 return createStringError(errc::not_supported, 694 "unable to write debug_addr address: %s", 695 toString(std::move(Err)).c_str()); 696 } 697 } 698 699 return Error::success(); 700 } 701 702 Error DWARFYAML::emitDebugStrOffsets(raw_ostream &OS, const Data &DI) { 703 assert(DI.DebugStrOffsets && "unexpected emitDebugStrOffsets() call"); 704 for (const DWARFYAML::StringOffsetsTable &Table : *DI.DebugStrOffsets) { 705 uint64_t Length; 706 if (Table.Length) 707 Length = *Table.Length; 708 else 709 // sizeof(version) + sizeof(padding) = 4 710 Length = 711 4 + Table.Offsets.size() * (Table.Format == dwarf::DWARF64 ? 8 : 4); 712 713 writeInitialLength(Table.Format, Length, OS, DI.IsLittleEndian); 714 writeInteger((uint16_t)Table.Version, OS, DI.IsLittleEndian); 715 writeInteger((uint16_t)Table.Padding, OS, DI.IsLittleEndian); 716 717 for (uint64_t Offset : Table.Offsets) 718 writeDWARFOffset(Offset, Table.Format, OS, DI.IsLittleEndian); 719 } 720 721 return Error::success(); 722 } 723 724 namespace { 725 /// Emits the header for a DebugNames section. 726 void emitDebugNamesHeader(raw_ostream &OS, bool IsLittleEndian, 727 uint32_t NameCount, uint32_t AbbrevSize, 728 uint32_t CombinedSizeOtherParts) { 729 // Use the same AugmentationString as AsmPrinter. 730 StringRef AugmentationString = "LLVM0700"; 731 size_t TotalSize = CombinedSizeOtherParts + 5 * sizeof(uint32_t) + 732 2 * sizeof(uint16_t) + sizeof(NameCount) + 733 sizeof(AbbrevSize) + AugmentationString.size(); 734 writeInteger(uint32_t(TotalSize), OS, IsLittleEndian); // Unit length 735 736 // Everything below is included in total size. 737 writeInteger(uint16_t(5), OS, IsLittleEndian); // Version 738 writeInteger(uint16_t(0), OS, IsLittleEndian); // Padding 739 writeInteger(uint32_t(1), OS, IsLittleEndian); // Compilation Unit count 740 writeInteger(uint32_t(0), OS, IsLittleEndian); // Local Type Unit count 741 writeInteger(uint32_t(0), OS, IsLittleEndian); // Foreign Type Unit count 742 writeInteger(uint32_t(0), OS, IsLittleEndian); // Bucket count 743 writeInteger(NameCount, OS, IsLittleEndian); 744 writeInteger(AbbrevSize, OS, IsLittleEndian); 745 writeInteger(uint32_t(AugmentationString.size()), OS, IsLittleEndian); 746 OS.write(AugmentationString.data(), AugmentationString.size()); 747 } 748 749 /// Emits the abbreviations for a DebugNames section. 750 std::string 751 emitDebugNamesAbbrev(ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) { 752 std::string Data; 753 raw_string_ostream OS(Data); 754 for (const DWARFYAML::DebugNameAbbreviation &Abbrev : Abbrevs) { 755 encodeULEB128(Abbrev.Code, OS); 756 encodeULEB128(Abbrev.Tag, OS); 757 for (auto [Idx, Form] : Abbrev.Indices) { 758 encodeULEB128(Idx, OS); 759 encodeULEB128(Form, OS); 760 } 761 encodeULEB128(0, OS); 762 encodeULEB128(0, OS); 763 } 764 encodeULEB128(0, OS); 765 return Data; 766 } 767 768 /// Emits a simple CU offsets list for a DebugNames section containing a single 769 /// CU at offset 0. 770 std::string emitDebugNamesCUOffsets(bool IsLittleEndian) { 771 std::string Data; 772 raw_string_ostream OS(Data); 773 writeInteger(uint32_t(0), OS, IsLittleEndian); 774 return Data; 775 } 776 777 /// Emits the "NameTable" for a DebugNames section; according to the spec, it 778 /// consists of two arrays: an array of string offsets, followed immediately by 779 /// an array of entry offsets. The string offsets are emitted in the order 780 /// provided in `Entries`. 781 std::string emitDebugNamesNameTable( 782 bool IsLittleEndian, 783 const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> &Entries, 784 ArrayRef<uint32_t> EntryPoolOffsets) { 785 assert(Entries.size() == EntryPoolOffsets.size()); 786 787 std::string Data; 788 raw_string_ostream OS(Data); 789 790 for (uint32_t Strp : make_first_range(Entries)) 791 writeInteger(Strp, OS, IsLittleEndian); 792 for (uint32_t PoolOffset : EntryPoolOffsets) 793 writeInteger(PoolOffset, OS, IsLittleEndian); 794 return Data; 795 } 796 797 /// Groups entries based on their name (strp) code and returns a map. 798 DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> 799 groupEntries(ArrayRef<DWARFYAML::DebugNameEntry> Entries) { 800 DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> StrpToEntries; 801 for (const DWARFYAML::DebugNameEntry &Entry : Entries) 802 StrpToEntries[Entry.NameStrp].push_back(Entry); 803 return StrpToEntries; 804 } 805 806 /// Finds the abbreviation whose code is AbbrevCode and returns a list 807 /// containing the expected size of all non-zero-length forms. 808 Expected<SmallVector<uint8_t>> 809 getNonZeroDataSizesFor(uint32_t AbbrevCode, 810 ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) { 811 const auto *AbbrevIt = find_if(Abbrevs, [&](const auto &Abbrev) { 812 return Abbrev.Code.value == AbbrevCode; 813 }); 814 if (AbbrevIt == Abbrevs.end()) 815 return createStringError(inconvertibleErrorCode(), 816 "did not find an Abbreviation for this code"); 817 818 SmallVector<uint8_t> DataSizes; 819 dwarf::FormParams Params{/*Version=*/5, /*AddrSize=*/4, dwarf::DWARF32}; 820 for (auto [Idx, Form] : AbbrevIt->Indices) { 821 std::optional<uint8_t> FormSize = dwarf::getFixedFormByteSize(Form, Params); 822 if (!FormSize) 823 return createStringError(inconvertibleErrorCode(), 824 "unsupported Form for YAML debug_names emitter"); 825 if (FormSize == 0) 826 continue; 827 DataSizes.push_back(*FormSize); 828 } 829 return DataSizes; 830 } 831 832 struct PoolOffsetsAndData { 833 std::string PoolData; 834 std::vector<uint32_t> PoolOffsets; 835 }; 836 837 /// Emits the entry pool and returns an array of offsets containing the start 838 /// offset for the entries of each unique name. 839 /// Verifies that the provided number of data values match those expected by 840 /// the abbreviation table. 841 Expected<PoolOffsetsAndData> emitDebugNamesEntryPool( 842 bool IsLittleEndian, 843 const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> 844 &StrpToEntries, 845 ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) { 846 PoolOffsetsAndData Result; 847 raw_string_ostream OS(Result.PoolData); 848 849 for (ArrayRef<DWARFYAML::DebugNameEntry> EntriesWithSameName : 850 make_second_range(StrpToEntries)) { 851 Result.PoolOffsets.push_back(Result.PoolData.size()); 852 853 for (const DWARFYAML::DebugNameEntry &Entry : EntriesWithSameName) { 854 encodeULEB128(Entry.Code, OS); 855 856 Expected<SmallVector<uint8_t>> DataSizes = 857 getNonZeroDataSizesFor(Entry.Code, Abbrevs); 858 if (!DataSizes) 859 return DataSizes.takeError(); 860 if (DataSizes->size() != Entry.Values.size()) 861 return createStringError( 862 inconvertibleErrorCode(), 863 "mismatch between provided and required number of values"); 864 865 for (auto [Value, ValueSize] : zip_equal(Entry.Values, *DataSizes)) 866 if (Error E = 867 writeVariableSizedInteger(Value, ValueSize, OS, IsLittleEndian)) 868 return std::move(E); 869 } 870 encodeULEB128(0, OS); 871 } 872 873 return Result; 874 } 875 } // namespace 876 877 Error DWARFYAML::emitDebugNames(raw_ostream &OS, const Data &DI) { 878 assert(DI.DebugNames && "unexpected emitDebugNames() call"); 879 const DebugNamesSection DebugNames = DI.DebugNames.value(); 880 881 DenseMap<uint32_t, std::vector<DebugNameEntry>> StrpToEntries = 882 groupEntries(DebugNames.Entries); 883 884 // Emit all sub-sections into individual strings so that we may compute 885 // relative offsets and sizes. 886 Expected<PoolOffsetsAndData> PoolInfo = emitDebugNamesEntryPool( 887 DI.IsLittleEndian, StrpToEntries, DebugNames.Abbrevs); 888 if (!PoolInfo) 889 return PoolInfo.takeError(); 890 std::string NamesTableData = emitDebugNamesNameTable( 891 DI.IsLittleEndian, StrpToEntries, PoolInfo->PoolOffsets); 892 893 std::string AbbrevData = emitDebugNamesAbbrev(DebugNames.Abbrevs); 894 std::string CUOffsetsData = emitDebugNamesCUOffsets(DI.IsLittleEndian); 895 896 size_t TotalSize = PoolInfo->PoolData.size() + NamesTableData.size() + 897 AbbrevData.size() + CUOffsetsData.size(); 898 899 // Start real emission by combining all individual strings. 900 emitDebugNamesHeader(OS, DI.IsLittleEndian, StrpToEntries.size(), 901 AbbrevData.size(), TotalSize); 902 OS.write(CUOffsetsData.data(), CUOffsetsData.size()); 903 // No local TUs, no foreign TUs, no hash lookups table. 904 OS.write(NamesTableData.data(), NamesTableData.size()); 905 OS.write(AbbrevData.data(), AbbrevData.size()); 906 OS.write(PoolInfo->PoolData.data(), PoolInfo->PoolData.size()); 907 908 return Error::success(); 909 } 910 911 static Error checkOperandCount(StringRef EncodingString, 912 ArrayRef<yaml::Hex64> Values, 913 uint64_t ExpectedOperands) { 914 if (Values.size() != ExpectedOperands) 915 return createStringError( 916 errc::invalid_argument, 917 "invalid number (%zu) of operands for the operator: %s, %" PRIu64 918 " expected", 919 Values.size(), EncodingString.str().c_str(), ExpectedOperands); 920 921 return Error::success(); 922 } 923 924 static Error writeListEntryAddress(StringRef EncodingName, raw_ostream &OS, 925 uint64_t Addr, uint8_t AddrSize, 926 bool IsLittleEndian) { 927 if (Error Err = writeVariableSizedInteger(Addr, AddrSize, OS, IsLittleEndian)) 928 return createStringError(errc::invalid_argument, 929 "unable to write address for the operator %s: %s", 930 EncodingName.str().c_str(), 931 toString(std::move(Err)).c_str()); 932 933 return Error::success(); 934 } 935 936 static Expected<uint64_t> 937 writeDWARFExpression(raw_ostream &OS, 938 const DWARFYAML::DWARFOperation &Operation, 939 uint8_t AddrSize, bool IsLittleEndian) { 940 auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error { 941 return checkOperandCount(dwarf::OperationEncodingString(Operation.Operator), 942 Operation.Values, ExpectedOperands); 943 }; 944 945 uint64_t ExpressionBegin = OS.tell(); 946 writeInteger((uint8_t)Operation.Operator, OS, IsLittleEndian); 947 switch (Operation.Operator) { 948 case dwarf::DW_OP_consts: 949 if (Error Err = CheckOperands(1)) 950 return std::move(Err); 951 encodeSLEB128(Operation.Values[0], OS); 952 break; 953 case dwarf::DW_OP_stack_value: 954 if (Error Err = CheckOperands(0)) 955 return std::move(Err); 956 break; 957 default: 958 StringRef EncodingStr = dwarf::OperationEncodingString(Operation.Operator); 959 return createStringError(errc::not_supported, 960 "DWARF expression: " + 961 (EncodingStr.empty() 962 ? "0x" + utohexstr(Operation.Operator) 963 : EncodingStr) + 964 " is not supported"); 965 } 966 return OS.tell() - ExpressionBegin; 967 } 968 969 static Expected<uint64_t> writeListEntry(raw_ostream &OS, 970 const DWARFYAML::RnglistEntry &Entry, 971 uint8_t AddrSize, 972 bool IsLittleEndian) { 973 uint64_t BeginOffset = OS.tell(); 974 writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian); 975 976 StringRef EncodingName = dwarf::RangeListEncodingString(Entry.Operator); 977 978 auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error { 979 return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands); 980 }; 981 982 auto WriteAddress = [&](uint64_t Addr) -> Error { 983 return writeListEntryAddress(EncodingName, OS, Addr, AddrSize, 984 IsLittleEndian); 985 }; 986 987 switch (Entry.Operator) { 988 case dwarf::DW_RLE_end_of_list: 989 if (Error Err = CheckOperands(0)) 990 return std::move(Err); 991 break; 992 case dwarf::DW_RLE_base_addressx: 993 if (Error Err = CheckOperands(1)) 994 return std::move(Err); 995 encodeULEB128(Entry.Values[0], OS); 996 break; 997 case dwarf::DW_RLE_startx_endx: 998 case dwarf::DW_RLE_startx_length: 999 case dwarf::DW_RLE_offset_pair: 1000 if (Error Err = CheckOperands(2)) 1001 return std::move(Err); 1002 encodeULEB128(Entry.Values[0], OS); 1003 encodeULEB128(Entry.Values[1], OS); 1004 break; 1005 case dwarf::DW_RLE_base_address: 1006 if (Error Err = CheckOperands(1)) 1007 return std::move(Err); 1008 if (Error Err = WriteAddress(Entry.Values[0])) 1009 return std::move(Err); 1010 break; 1011 case dwarf::DW_RLE_start_end: 1012 if (Error Err = CheckOperands(2)) 1013 return std::move(Err); 1014 if (Error Err = WriteAddress(Entry.Values[0])) 1015 return std::move(Err); 1016 cantFail(WriteAddress(Entry.Values[1])); 1017 break; 1018 case dwarf::DW_RLE_start_length: 1019 if (Error Err = CheckOperands(2)) 1020 return std::move(Err); 1021 if (Error Err = WriteAddress(Entry.Values[0])) 1022 return std::move(Err); 1023 encodeULEB128(Entry.Values[1], OS); 1024 break; 1025 } 1026 1027 return OS.tell() - BeginOffset; 1028 } 1029 1030 static Expected<uint64_t> writeListEntry(raw_ostream &OS, 1031 const DWARFYAML::LoclistEntry &Entry, 1032 uint8_t AddrSize, 1033 bool IsLittleEndian) { 1034 uint64_t BeginOffset = OS.tell(); 1035 writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian); 1036 1037 StringRef EncodingName = dwarf::LocListEncodingString(Entry.Operator); 1038 1039 auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error { 1040 return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands); 1041 }; 1042 1043 auto WriteAddress = [&](uint64_t Addr) -> Error { 1044 return writeListEntryAddress(EncodingName, OS, Addr, AddrSize, 1045 IsLittleEndian); 1046 }; 1047 1048 auto WriteDWARFOperations = [&]() -> Error { 1049 std::string OpBuffer; 1050 raw_string_ostream OpBufferOS(OpBuffer); 1051 uint64_t DescriptionsLength = 0; 1052 1053 for (const DWARFYAML::DWARFOperation &Op : Entry.Descriptions) { 1054 if (Expected<uint64_t> OpSize = 1055 writeDWARFExpression(OpBufferOS, Op, AddrSize, IsLittleEndian)) 1056 DescriptionsLength += *OpSize; 1057 else 1058 return OpSize.takeError(); 1059 } 1060 1061 if (Entry.DescriptionsLength) 1062 DescriptionsLength = *Entry.DescriptionsLength; 1063 else 1064 DescriptionsLength = OpBuffer.size(); 1065 1066 encodeULEB128(DescriptionsLength, OS); 1067 OS.write(OpBuffer.data(), OpBuffer.size()); 1068 1069 return Error::success(); 1070 }; 1071 1072 switch (Entry.Operator) { 1073 case dwarf::DW_LLE_end_of_list: 1074 if (Error Err = CheckOperands(0)) 1075 return std::move(Err); 1076 break; 1077 case dwarf::DW_LLE_base_addressx: 1078 if (Error Err = CheckOperands(1)) 1079 return std::move(Err); 1080 encodeULEB128(Entry.Values[0], OS); 1081 break; 1082 case dwarf::DW_LLE_startx_endx: 1083 case dwarf::DW_LLE_startx_length: 1084 case dwarf::DW_LLE_offset_pair: 1085 if (Error Err = CheckOperands(2)) 1086 return std::move(Err); 1087 encodeULEB128(Entry.Values[0], OS); 1088 encodeULEB128(Entry.Values[1], OS); 1089 if (Error Err = WriteDWARFOperations()) 1090 return std::move(Err); 1091 break; 1092 case dwarf::DW_LLE_default_location: 1093 if (Error Err = CheckOperands(0)) 1094 return std::move(Err); 1095 if (Error Err = WriteDWARFOperations()) 1096 return std::move(Err); 1097 break; 1098 case dwarf::DW_LLE_base_address: 1099 if (Error Err = CheckOperands(1)) 1100 return std::move(Err); 1101 if (Error Err = WriteAddress(Entry.Values[0])) 1102 return std::move(Err); 1103 break; 1104 case dwarf::DW_LLE_start_end: 1105 if (Error Err = CheckOperands(2)) 1106 return std::move(Err); 1107 if (Error Err = WriteAddress(Entry.Values[0])) 1108 return std::move(Err); 1109 cantFail(WriteAddress(Entry.Values[1])); 1110 if (Error Err = WriteDWARFOperations()) 1111 return std::move(Err); 1112 break; 1113 case dwarf::DW_LLE_start_length: 1114 if (Error Err = CheckOperands(2)) 1115 return std::move(Err); 1116 if (Error Err = WriteAddress(Entry.Values[0])) 1117 return std::move(Err); 1118 encodeULEB128(Entry.Values[1], OS); 1119 if (Error Err = WriteDWARFOperations()) 1120 return std::move(Err); 1121 break; 1122 } 1123 1124 return OS.tell() - BeginOffset; 1125 } 1126 1127 template <typename EntryType> 1128 static Error writeDWARFLists(raw_ostream &OS, 1129 ArrayRef<DWARFYAML::ListTable<EntryType>> Tables, 1130 bool IsLittleEndian, bool Is64BitAddrSize) { 1131 for (const DWARFYAML::ListTable<EntryType> &Table : Tables) { 1132 // sizeof(version) + sizeof(address_size) + sizeof(segment_selector_size) + 1133 // sizeof(offset_entry_count) = 8 1134 uint64_t Length = 8; 1135 1136 uint8_t AddrSize; 1137 if (Table.AddrSize) 1138 AddrSize = *Table.AddrSize; 1139 else 1140 AddrSize = Is64BitAddrSize ? 8 : 4; 1141 1142 // Since the length of the current range/location lists entry is 1143 // undetermined yet, we firstly write the content of the range/location 1144 // lists to a buffer to calculate the length and then serialize the buffer 1145 // content to the actual output stream. 1146 std::string ListBuffer; 1147 raw_string_ostream ListBufferOS(ListBuffer); 1148 1149 // Offsets holds offsets for each range/location list. The i-th element is 1150 // the offset from the beginning of the first range/location list to the 1151 // location of the i-th range list. 1152 std::vector<uint64_t> Offsets; 1153 1154 for (const DWARFYAML::ListEntries<EntryType> &List : Table.Lists) { 1155 Offsets.push_back(ListBufferOS.tell()); 1156 if (List.Content) { 1157 List.Content->writeAsBinary(ListBufferOS, UINT64_MAX); 1158 Length += List.Content->binary_size(); 1159 } else if (List.Entries) { 1160 for (const EntryType &Entry : *List.Entries) { 1161 Expected<uint64_t> EntrySize = 1162 writeListEntry(ListBufferOS, Entry, AddrSize, IsLittleEndian); 1163 if (!EntrySize) 1164 return EntrySize.takeError(); 1165 Length += *EntrySize; 1166 } 1167 } 1168 } 1169 1170 // If the offset_entry_count field isn't specified, yaml2obj will infer it 1171 // from the 'Offsets' field in the YAML description. If the 'Offsets' field 1172 // isn't specified either, yaml2obj will infer it from the auto-generated 1173 // offsets. 1174 uint32_t OffsetEntryCount; 1175 if (Table.OffsetEntryCount) 1176 OffsetEntryCount = *Table.OffsetEntryCount; 1177 else 1178 OffsetEntryCount = Table.Offsets ? Table.Offsets->size() : Offsets.size(); 1179 uint64_t OffsetsSize = 1180 OffsetEntryCount * (Table.Format == dwarf::DWARF64 ? 8 : 4); 1181 Length += OffsetsSize; 1182 1183 // If the length is specified in the YAML description, we use it instead of 1184 // the actual length. 1185 if (Table.Length) 1186 Length = *Table.Length; 1187 1188 writeInitialLength(Table.Format, Length, OS, IsLittleEndian); 1189 writeInteger((uint16_t)Table.Version, OS, IsLittleEndian); 1190 writeInteger((uint8_t)AddrSize, OS, IsLittleEndian); 1191 writeInteger((uint8_t)Table.SegSelectorSize, OS, IsLittleEndian); 1192 writeInteger((uint32_t)OffsetEntryCount, OS, IsLittleEndian); 1193 1194 auto EmitOffsets = [&](ArrayRef<uint64_t> Offsets, uint64_t OffsetsSize) { 1195 for (uint64_t Offset : Offsets) 1196 writeDWARFOffset(OffsetsSize + Offset, Table.Format, OS, 1197 IsLittleEndian); 1198 }; 1199 1200 if (Table.Offsets) 1201 EmitOffsets(ArrayRef<uint64_t>((const uint64_t *)Table.Offsets->data(), 1202 Table.Offsets->size()), 1203 0); 1204 else if (OffsetEntryCount != 0) 1205 EmitOffsets(Offsets, OffsetsSize); 1206 1207 OS.write(ListBuffer.data(), ListBuffer.size()); 1208 } 1209 1210 return Error::success(); 1211 } 1212 1213 Error DWARFYAML::emitDebugRnglists(raw_ostream &OS, const Data &DI) { 1214 assert(DI.DebugRnglists && "unexpected emitDebugRnglists() call"); 1215 return writeDWARFLists<DWARFYAML::RnglistEntry>( 1216 OS, *DI.DebugRnglists, DI.IsLittleEndian, DI.Is64BitAddrSize); 1217 } 1218 1219 Error DWARFYAML::emitDebugLoclists(raw_ostream &OS, const Data &DI) { 1220 assert(DI.DebugLoclists && "unexpected emitDebugRnglists() call"); 1221 return writeDWARFLists<DWARFYAML::LoclistEntry>( 1222 OS, *DI.DebugLoclists, DI.IsLittleEndian, DI.Is64BitAddrSize); 1223 } 1224 1225 std::function<Error(raw_ostream &, const DWARFYAML::Data &)> 1226 DWARFYAML::getDWARFEmitterByName(StringRef SecName) { 1227 auto EmitFunc = 1228 StringSwitch< 1229 std::function<Error(raw_ostream &, const DWARFYAML::Data &)>>(SecName) 1230 .Case("debug_abbrev", DWARFYAML::emitDebugAbbrev) 1231 .Case("debug_addr", DWARFYAML::emitDebugAddr) 1232 .Case("debug_aranges", DWARFYAML::emitDebugAranges) 1233 .Case("debug_gnu_pubnames", DWARFYAML::emitDebugGNUPubnames) 1234 .Case("debug_gnu_pubtypes", DWARFYAML::emitDebugGNUPubtypes) 1235 .Case("debug_info", DWARFYAML::emitDebugInfo) 1236 .Case("debug_line", DWARFYAML::emitDebugLine) 1237 .Case("debug_loclists", DWARFYAML::emitDebugLoclists) 1238 .Case("debug_pubnames", DWARFYAML::emitDebugPubnames) 1239 .Case("debug_pubtypes", DWARFYAML::emitDebugPubtypes) 1240 .Case("debug_ranges", DWARFYAML::emitDebugRanges) 1241 .Case("debug_rnglists", DWARFYAML::emitDebugRnglists) 1242 .Case("debug_str", DWARFYAML::emitDebugStr) 1243 .Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets) 1244 .Case("debug_names", DWARFYAML::emitDebugNames) 1245 .Default([&](raw_ostream &, const DWARFYAML::Data &) { 1246 return createStringError(errc::not_supported, 1247 SecName + " is not supported"); 1248 }); 1249 1250 return EmitFunc; 1251 } 1252 1253 static Error 1254 emitDebugSectionImpl(const DWARFYAML::Data &DI, StringRef Sec, 1255 StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) { 1256 std::string Data; 1257 raw_string_ostream DebugInfoStream(Data); 1258 1259 auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Sec); 1260 1261 if (Error Err = EmitFunc(DebugInfoStream, DI)) 1262 return Err; 1263 DebugInfoStream.flush(); 1264 if (!Data.empty()) 1265 OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data); 1266 1267 return Error::success(); 1268 } 1269 1270 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> 1271 DWARFYAML::emitDebugSections(StringRef YAMLString, bool IsLittleEndian, 1272 bool Is64BitAddrSize) { 1273 auto CollectDiagnostic = [](const SMDiagnostic &Diag, void *DiagContext) { 1274 *static_cast<SMDiagnostic *>(DiagContext) = Diag; 1275 }; 1276 1277 SMDiagnostic GeneratedDiag; 1278 yaml::Input YIn(YAMLString, /*Ctxt=*/nullptr, CollectDiagnostic, 1279 &GeneratedDiag); 1280 1281 DWARFYAML::Data DI; 1282 DI.IsLittleEndian = IsLittleEndian; 1283 DI.Is64BitAddrSize = Is64BitAddrSize; 1284 1285 YIn >> DI; 1286 if (YIn.error()) 1287 return createStringError(YIn.error(), GeneratedDiag.getMessage()); 1288 1289 StringMap<std::unique_ptr<MemoryBuffer>> DebugSections; 1290 Error Err = Error::success(); 1291 1292 for (StringRef SecName : DI.getNonEmptySectionNames()) 1293 Err = joinErrors(std::move(Err), 1294 emitDebugSectionImpl(DI, SecName, DebugSections)); 1295 1296 if (Err) 1297 return std::move(Err); 1298 return std::move(DebugSections); 1299 } 1300