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