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/BinaryFormat/Dwarf.h" 19 #include "llvm/ObjectYAML/DWARFYAML.h" 20 #include "llvm/Support/Errc.h" 21 #include "llvm/Support/Error.h" 22 #include "llvm/Support/Host.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 <algorithm> 31 #include <cassert> 32 #include <cstddef> 33 #include <cstdint> 34 #include <memory> 35 #include <string> 36 #include <vector> 37 38 using namespace llvm; 39 40 template <typename T> 41 static void writeInteger(T Integer, raw_ostream &OS, bool IsLittleEndian) { 42 if (IsLittleEndian != sys::IsLittleEndianHost) 43 sys::swapByteOrder(Integer); 44 OS.write(reinterpret_cast<char *>(&Integer), sizeof(T)); 45 } 46 47 static Error writeVariableSizedInteger(uint64_t Integer, size_t Size, 48 raw_ostream &OS, bool IsLittleEndian) { 49 if (8 == Size) 50 writeInteger((uint64_t)Integer, OS, IsLittleEndian); 51 else if (4 == Size) 52 writeInteger((uint32_t)Integer, OS, IsLittleEndian); 53 else if (2 == Size) 54 writeInteger((uint16_t)Integer, OS, IsLittleEndian); 55 else if (1 == Size) 56 writeInteger((uint8_t)Integer, OS, IsLittleEndian); 57 else 58 return createStringError(errc::not_supported, 59 "invalid integer write size: %zu", Size); 60 61 return Error::success(); 62 } 63 64 static void ZeroFillBytes(raw_ostream &OS, size_t Size) { 65 std::vector<uint8_t> FillData; 66 FillData.insert(FillData.begin(), Size, 0); 67 OS.write(reinterpret_cast<char *>(FillData.data()), Size); 68 } 69 70 static void writeInitialLength(const DWARFYAML::InitialLength &Length, 71 raw_ostream &OS, bool IsLittleEndian) { 72 writeInteger((uint32_t)Length.TotalLength, OS, IsLittleEndian); 73 if (Length.isDWARF64()) 74 writeInteger((uint64_t)Length.TotalLength64, OS, IsLittleEndian); 75 } 76 77 static void writeInitialLength(const dwarf::DwarfFormat Format, 78 const uint64_t Length, raw_ostream &OS, 79 bool IsLittleEndian) { 80 bool IsDWARF64 = Format == dwarf::DWARF64; 81 if (IsDWARF64) 82 cantFail(writeVariableSizedInteger(dwarf::DW_LENGTH_DWARF64, 4, OS, 83 IsLittleEndian)); 84 cantFail( 85 writeVariableSizedInteger(Length, IsDWARF64 ? 8 : 4, OS, IsLittleEndian)); 86 } 87 88 static void writeDWARFOffset(uint64_t Offset, dwarf::DwarfFormat Format, 89 raw_ostream &OS, bool IsLittleEndian) { 90 cantFail(writeVariableSizedInteger(Offset, Format == dwarf::DWARF64 ? 8 : 4, 91 OS, IsLittleEndian)); 92 } 93 94 Error DWARFYAML::emitDebugStr(raw_ostream &OS, const DWARFYAML::Data &DI) { 95 for (auto Str : DI.DebugStrings) { 96 OS.write(Str.data(), Str.size()); 97 OS.write('\0'); 98 } 99 100 return Error::success(); 101 } 102 103 Error DWARFYAML::emitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) { 104 uint64_t AbbrevCode = 0; 105 for (auto AbbrevDecl : DI.AbbrevDecls) { 106 AbbrevCode = AbbrevDecl.Code ? (uint64_t)*AbbrevDecl.Code : AbbrevCode + 1; 107 encodeULEB128(AbbrevCode, OS); 108 encodeULEB128(AbbrevDecl.Tag, OS); 109 OS.write(AbbrevDecl.Children); 110 for (auto Attr : AbbrevDecl.Attributes) { 111 encodeULEB128(Attr.Attribute, OS); 112 encodeULEB128(Attr.Form, OS); 113 if (Attr.Form == dwarf::DW_FORM_implicit_const) 114 encodeSLEB128(Attr.Value, OS); 115 } 116 encodeULEB128(0, OS); 117 encodeULEB128(0, OS); 118 } 119 120 // The abbreviations for a given compilation unit end with an entry consisting 121 // of a 0 byte for the abbreviation code. 122 OS.write_zeros(1); 123 124 return Error::success(); 125 } 126 127 Error DWARFYAML::emitDebugAranges(raw_ostream &OS, const DWARFYAML::Data &DI) { 128 for (auto Range : DI.ARanges) { 129 auto HeaderStart = OS.tell(); 130 writeInitialLength(Range.Format, Range.Length, OS, DI.IsLittleEndian); 131 writeInteger((uint16_t)Range.Version, OS, DI.IsLittleEndian); 132 writeDWARFOffset(Range.CuOffset, Range.Format, OS, DI.IsLittleEndian); 133 writeInteger((uint8_t)Range.AddrSize, OS, DI.IsLittleEndian); 134 writeInteger((uint8_t)Range.SegSize, OS, DI.IsLittleEndian); 135 136 auto HeaderSize = OS.tell() - HeaderStart; 137 auto FirstDescriptor = alignTo(HeaderSize, Range.AddrSize * 2); 138 ZeroFillBytes(OS, FirstDescriptor - HeaderSize); 139 140 for (auto Descriptor : Range.Descriptors) { 141 if (Error Err = writeVariableSizedInteger( 142 Descriptor.Address, Range.AddrSize, OS, DI.IsLittleEndian)) 143 return createStringError(errc::not_supported, 144 "unable to write debug_aranges address: %s", 145 toString(std::move(Err)).c_str()); 146 cantFail(writeVariableSizedInteger(Descriptor.Length, Range.AddrSize, OS, 147 DI.IsLittleEndian)); 148 } 149 ZeroFillBytes(OS, Range.AddrSize * 2); 150 } 151 152 return Error::success(); 153 } 154 155 Error DWARFYAML::emitDebugRanges(raw_ostream &OS, const DWARFYAML::Data &DI) { 156 const size_t RangesOffset = OS.tell(); 157 uint64_t EntryIndex = 0; 158 for (auto DebugRanges : DI.DebugRanges) { 159 const size_t CurrOffset = OS.tell() - RangesOffset; 160 if (DebugRanges.Offset && (uint64_t)*DebugRanges.Offset < CurrOffset) 161 return createStringError(errc::invalid_argument, 162 "'Offset' for 'debug_ranges' with index " + 163 Twine(EntryIndex) + 164 " must be greater than or equal to the " 165 "number of bytes written already (0x" + 166 Twine::utohexstr(CurrOffset) + ")"); 167 if (DebugRanges.Offset) 168 ZeroFillBytes(OS, *DebugRanges.Offset - CurrOffset); 169 170 uint8_t AddrSize; 171 if (DebugRanges.AddrSize) 172 AddrSize = *DebugRanges.AddrSize; 173 else 174 AddrSize = DI.Is64BitAddrSize ? 8 : 4; 175 for (auto Entry : DebugRanges.Entries) { 176 if (Error Err = writeVariableSizedInteger(Entry.LowOffset, AddrSize, OS, 177 DI.IsLittleEndian)) 178 return createStringError( 179 errc::not_supported, 180 "unable to write debug_ranges address offset: %s", 181 toString(std::move(Err)).c_str()); 182 cantFail(writeVariableSizedInteger(Entry.HighOffset, AddrSize, OS, 183 DI.IsLittleEndian)); 184 } 185 ZeroFillBytes(OS, AddrSize * 2); 186 ++EntryIndex; 187 } 188 189 return Error::success(); 190 } 191 192 Error DWARFYAML::emitPubSection(raw_ostream &OS, 193 const DWARFYAML::PubSection &Sect, 194 bool IsLittleEndian, bool IsGNUPubSec) { 195 writeInitialLength(Sect.Length, OS, IsLittleEndian); 196 writeInteger((uint16_t)Sect.Version, OS, IsLittleEndian); 197 writeInteger((uint32_t)Sect.UnitOffset, OS, IsLittleEndian); 198 writeInteger((uint32_t)Sect.UnitSize, OS, IsLittleEndian); 199 for (auto Entry : Sect.Entries) { 200 writeInteger((uint32_t)Entry.DieOffset, OS, IsLittleEndian); 201 if (IsGNUPubSec) 202 writeInteger((uint8_t)Entry.Descriptor, OS, IsLittleEndian); 203 OS.write(Entry.Name.data(), Entry.Name.size()); 204 OS.write('\0'); 205 } 206 207 return Error::success(); 208 } 209 210 static Expected<uint64_t> writeDIE(ArrayRef<DWARFYAML::Abbrev> AbbrevDecls, 211 const DWARFYAML::Unit &Unit, 212 const DWARFYAML::Entry &Entry, 213 raw_ostream &OS, bool IsLittleEndian) { 214 uint64_t EntryBegin = OS.tell(); 215 encodeULEB128(Entry.AbbrCode, OS); 216 uint32_t AbbrCode = Entry.AbbrCode; 217 if (AbbrCode == 0 || Entry.Values.empty()) 218 return OS.tell() - EntryBegin; 219 220 if (AbbrCode > AbbrevDecls.size()) 221 return createStringError( 222 errc::invalid_argument, 223 "abbrev code must be less than or equal to the number of " 224 "entries in abbreviation table"); 225 const DWARFYAML::Abbrev &Abbrev = AbbrevDecls[AbbrCode - 1]; 226 auto FormVal = Entry.Values.begin(); 227 auto AbbrForm = Abbrev.Attributes.begin(); 228 for (; FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end(); 229 ++FormVal, ++AbbrForm) { 230 dwarf::Form Form = AbbrForm->Form; 231 bool Indirect; 232 do { 233 Indirect = false; 234 switch (Form) { 235 case dwarf::DW_FORM_addr: 236 // TODO: Test this error. 237 if (Error Err = writeVariableSizedInteger( 238 FormVal->Value, Unit.FormParams.AddrSize, OS, IsLittleEndian)) 239 return std::move(Err); 240 break; 241 case dwarf::DW_FORM_ref_addr: 242 // TODO: Test this error. 243 if (Error Err = writeVariableSizedInteger( 244 FormVal->Value, Unit.FormParams.getRefAddrByteSize(), OS, 245 IsLittleEndian)) 246 return std::move(Err); 247 break; 248 case dwarf::DW_FORM_exprloc: 249 case dwarf::DW_FORM_block: 250 encodeULEB128(FormVal->BlockData.size(), OS); 251 OS.write((const char *)FormVal->BlockData.data(), 252 FormVal->BlockData.size()); 253 break; 254 case dwarf::DW_FORM_block1: { 255 writeInteger((uint8_t)FormVal->BlockData.size(), OS, IsLittleEndian); 256 OS.write((const char *)FormVal->BlockData.data(), 257 FormVal->BlockData.size()); 258 break; 259 } 260 case dwarf::DW_FORM_block2: { 261 writeInteger((uint16_t)FormVal->BlockData.size(), OS, IsLittleEndian); 262 OS.write((const char *)FormVal->BlockData.data(), 263 FormVal->BlockData.size()); 264 break; 265 } 266 case dwarf::DW_FORM_block4: { 267 writeInteger((uint32_t)FormVal->BlockData.size(), OS, IsLittleEndian); 268 OS.write((const char *)FormVal->BlockData.data(), 269 FormVal->BlockData.size()); 270 break; 271 } 272 case dwarf::DW_FORM_strx: 273 case dwarf::DW_FORM_addrx: 274 case dwarf::DW_FORM_rnglistx: 275 case dwarf::DW_FORM_loclistx: 276 case dwarf::DW_FORM_udata: 277 case dwarf::DW_FORM_ref_udata: 278 case dwarf::DW_FORM_GNU_addr_index: 279 case dwarf::DW_FORM_GNU_str_index: 280 encodeULEB128(FormVal->Value, OS); 281 break; 282 case dwarf::DW_FORM_data1: 283 case dwarf::DW_FORM_ref1: 284 case dwarf::DW_FORM_flag: 285 case dwarf::DW_FORM_strx1: 286 case dwarf::DW_FORM_addrx1: 287 writeInteger((uint8_t)FormVal->Value, OS, IsLittleEndian); 288 break; 289 case dwarf::DW_FORM_data2: 290 case dwarf::DW_FORM_ref2: 291 case dwarf::DW_FORM_strx2: 292 case dwarf::DW_FORM_addrx2: 293 writeInteger((uint16_t)FormVal->Value, OS, IsLittleEndian); 294 break; 295 case dwarf::DW_FORM_data4: 296 case dwarf::DW_FORM_ref4: 297 case dwarf::DW_FORM_ref_sup4: 298 case dwarf::DW_FORM_strx4: 299 case dwarf::DW_FORM_addrx4: 300 writeInteger((uint32_t)FormVal->Value, OS, IsLittleEndian); 301 break; 302 case dwarf::DW_FORM_data8: 303 case dwarf::DW_FORM_ref8: 304 case dwarf::DW_FORM_ref_sup8: 305 case dwarf::DW_FORM_ref_sig8: 306 writeInteger((uint64_t)FormVal->Value, OS, IsLittleEndian); 307 break; 308 case dwarf::DW_FORM_sdata: 309 encodeSLEB128(FormVal->Value, OS); 310 break; 311 case dwarf::DW_FORM_string: 312 OS.write(FormVal->CStr.data(), FormVal->CStr.size()); 313 OS.write('\0'); 314 break; 315 case dwarf::DW_FORM_indirect: 316 encodeULEB128(FormVal->Value, OS); 317 Indirect = true; 318 Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value); 319 ++FormVal; 320 break; 321 case dwarf::DW_FORM_strp: 322 case dwarf::DW_FORM_sec_offset: 323 case dwarf::DW_FORM_GNU_ref_alt: 324 case dwarf::DW_FORM_GNU_strp_alt: 325 case dwarf::DW_FORM_line_strp: 326 case dwarf::DW_FORM_strp_sup: 327 cantFail(writeVariableSizedInteger( 328 FormVal->Value, Unit.FormParams.getDwarfOffsetByteSize(), OS, 329 IsLittleEndian)); 330 break; 331 default: 332 break; 333 } 334 } while (Indirect); 335 } 336 337 return OS.tell() - EntryBegin; 338 } 339 340 Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) { 341 for (const DWARFYAML::Unit &Unit : DI.CompileUnits) { 342 uint64_t Length = 3; // sizeof(version) + sizeof(address_size) 343 Length += Unit.FormParams.Version >= 5 ? 1 : 0; // sizeof(unit_type) 344 Length += 345 Unit.FormParams.getDwarfOffsetByteSize(); // sizeof(debug_abbrev_offset) 346 347 // Since the length of the current compilation unit is undetermined yet, we 348 // firstly write the content of the compilation unit to a buffer to 349 // calculate it and then serialize the buffer content to the actual output 350 // stream. 351 std::string EntryBuffer; 352 raw_string_ostream EntryBufferOS(EntryBuffer); 353 354 for (const DWARFYAML::Entry &Entry : Unit.Entries) { 355 if (Expected<uint64_t> EntryLength = writeDIE( 356 DI.AbbrevDecls, Unit, Entry, EntryBufferOS, DI.IsLittleEndian)) 357 Length += *EntryLength; 358 else 359 return EntryLength.takeError(); 360 } 361 362 // If the length is specified in the YAML description, we use it instead of 363 // the actual length. 364 if (Unit.Length) 365 Length = *Unit.Length; 366 367 writeInitialLength(Unit.FormParams.Format, Length, OS, DI.IsLittleEndian); 368 writeInteger((uint16_t)Unit.FormParams.Version, OS, DI.IsLittleEndian); 369 if (Unit.FormParams.Version >= 5) { 370 writeInteger((uint8_t)Unit.Type, OS, DI.IsLittleEndian); 371 writeInteger((uint8_t)Unit.FormParams.AddrSize, OS, DI.IsLittleEndian); 372 writeDWARFOffset(Unit.AbbrOffset, Unit.FormParams.Format, OS, 373 DI.IsLittleEndian); 374 } else { 375 writeDWARFOffset(Unit.AbbrOffset, Unit.FormParams.Format, OS, 376 DI.IsLittleEndian); 377 writeInteger((uint8_t)Unit.FormParams.AddrSize, OS, DI.IsLittleEndian); 378 } 379 380 OS.write(EntryBuffer.data(), EntryBuffer.size()); 381 } 382 383 return Error::success(); 384 } 385 386 static void emitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) { 387 OS.write(File.Name.data(), File.Name.size()); 388 OS.write('\0'); 389 encodeULEB128(File.DirIdx, OS); 390 encodeULEB128(File.ModTime, OS); 391 encodeULEB128(File.Length, OS); 392 } 393 394 Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) { 395 for (const auto &LineTable : DI.DebugLines) { 396 writeInitialLength(LineTable.Format, LineTable.Length, OS, 397 DI.IsLittleEndian); 398 uint64_t SizeOfPrologueLength = LineTable.Format == dwarf::DWARF64 ? 8 : 4; 399 writeInteger((uint16_t)LineTable.Version, OS, DI.IsLittleEndian); 400 cantFail(writeVariableSizedInteger( 401 LineTable.PrologueLength, SizeOfPrologueLength, OS, DI.IsLittleEndian)); 402 writeInteger((uint8_t)LineTable.MinInstLength, OS, DI.IsLittleEndian); 403 if (LineTable.Version >= 4) 404 writeInteger((uint8_t)LineTable.MaxOpsPerInst, OS, DI.IsLittleEndian); 405 writeInteger((uint8_t)LineTable.DefaultIsStmt, OS, DI.IsLittleEndian); 406 writeInteger((uint8_t)LineTable.LineBase, OS, DI.IsLittleEndian); 407 writeInteger((uint8_t)LineTable.LineRange, OS, DI.IsLittleEndian); 408 writeInteger((uint8_t)LineTable.OpcodeBase, OS, DI.IsLittleEndian); 409 410 for (auto OpcodeLength : LineTable.StandardOpcodeLengths) 411 writeInteger((uint8_t)OpcodeLength, OS, DI.IsLittleEndian); 412 413 for (auto IncludeDir : LineTable.IncludeDirs) { 414 OS.write(IncludeDir.data(), IncludeDir.size()); 415 OS.write('\0'); 416 } 417 OS.write('\0'); 418 419 for (auto File : LineTable.Files) 420 emitFileEntry(OS, File); 421 OS.write('\0'); 422 423 for (auto Op : LineTable.Opcodes) { 424 writeInteger((uint8_t)Op.Opcode, OS, DI.IsLittleEndian); 425 if (Op.Opcode == 0) { 426 encodeULEB128(Op.ExtLen, OS); 427 writeInteger((uint8_t)Op.SubOpcode, OS, DI.IsLittleEndian); 428 switch (Op.SubOpcode) { 429 case dwarf::DW_LNE_set_address: 430 case dwarf::DW_LNE_set_discriminator: 431 // TODO: Test this error. 432 if (Error Err = writeVariableSizedInteger( 433 Op.Data, DI.CompileUnits[0].FormParams.AddrSize, OS, 434 DI.IsLittleEndian)) 435 return Err; 436 break; 437 case dwarf::DW_LNE_define_file: 438 emitFileEntry(OS, Op.FileEntry); 439 break; 440 case dwarf::DW_LNE_end_sequence: 441 break; 442 default: 443 for (auto OpByte : Op.UnknownOpcodeData) 444 writeInteger((uint8_t)OpByte, OS, DI.IsLittleEndian); 445 } 446 } else if (Op.Opcode < LineTable.OpcodeBase) { 447 switch (Op.Opcode) { 448 case dwarf::DW_LNS_copy: 449 case dwarf::DW_LNS_negate_stmt: 450 case dwarf::DW_LNS_set_basic_block: 451 case dwarf::DW_LNS_const_add_pc: 452 case dwarf::DW_LNS_set_prologue_end: 453 case dwarf::DW_LNS_set_epilogue_begin: 454 break; 455 456 case dwarf::DW_LNS_advance_pc: 457 case dwarf::DW_LNS_set_file: 458 case dwarf::DW_LNS_set_column: 459 case dwarf::DW_LNS_set_isa: 460 encodeULEB128(Op.Data, OS); 461 break; 462 463 case dwarf::DW_LNS_advance_line: 464 encodeSLEB128(Op.SData, OS); 465 break; 466 467 case dwarf::DW_LNS_fixed_advance_pc: 468 writeInteger((uint16_t)Op.Data, OS, DI.IsLittleEndian); 469 break; 470 471 default: 472 for (auto OpData : Op.StandardOpcodeData) { 473 encodeULEB128(OpData, OS); 474 } 475 } 476 } 477 } 478 } 479 480 return Error::success(); 481 } 482 483 Error DWARFYAML::emitDebugAddr(raw_ostream &OS, const Data &DI) { 484 for (const AddrTableEntry &TableEntry : DI.DebugAddr) { 485 uint8_t AddrSize; 486 if (TableEntry.AddrSize) 487 AddrSize = *TableEntry.AddrSize; 488 else 489 AddrSize = DI.Is64BitAddrSize ? 8 : 4; 490 491 uint64_t Length; 492 if (TableEntry.Length) 493 Length = (uint64_t)*TableEntry.Length; 494 else 495 // 2 (version) + 1 (address_size) + 1 (segment_selector_size) = 4 496 Length = 4 + (AddrSize + TableEntry.SegSelectorSize) * 497 TableEntry.SegAddrPairs.size(); 498 499 writeInitialLength(TableEntry.Format, Length, OS, DI.IsLittleEndian); 500 writeInteger((uint16_t)TableEntry.Version, OS, DI.IsLittleEndian); 501 writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian); 502 writeInteger((uint8_t)TableEntry.SegSelectorSize, OS, DI.IsLittleEndian); 503 504 for (const SegAddrPair &Pair : TableEntry.SegAddrPairs) { 505 if (TableEntry.SegSelectorSize != 0) 506 if (Error Err = writeVariableSizedInteger(Pair.Segment, 507 TableEntry.SegSelectorSize, 508 OS, DI.IsLittleEndian)) 509 return createStringError(errc::not_supported, 510 "unable to write debug_addr segment: %s", 511 toString(std::move(Err)).c_str()); 512 if (AddrSize != 0) 513 if (Error Err = writeVariableSizedInteger(Pair.Address, AddrSize, OS, 514 DI.IsLittleEndian)) 515 return createStringError(errc::not_supported, 516 "unable to write debug_addr address: %s", 517 toString(std::move(Err)).c_str()); 518 } 519 } 520 521 return Error::success(); 522 } 523 524 Error DWARFYAML::emitDebugStrOffsets(raw_ostream &OS, const Data &DI) { 525 assert(DI.DebugStrOffsets && "unexpected emitDebugStrOffsets() call"); 526 for (const DWARFYAML::StringOffsetsTable &Table : *DI.DebugStrOffsets) { 527 uint64_t Length; 528 if (Table.Length) 529 Length = *Table.Length; 530 else 531 // sizeof(version) + sizeof(padding) = 4 532 Length = 533 4 + Table.Offsets.size() * (Table.Format == dwarf::DWARF64 ? 8 : 4); 534 535 writeInitialLength(Table.Format, Length, OS, DI.IsLittleEndian); 536 writeInteger((uint16_t)Table.Version, OS, DI.IsLittleEndian); 537 writeInteger((uint16_t)Table.Padding, OS, DI.IsLittleEndian); 538 539 for (uint64_t Offset : Table.Offsets) 540 writeDWARFOffset(Offset, Table.Format, OS, DI.IsLittleEndian); 541 } 542 543 return Error::success(); 544 } 545 546 static Error checkOperandCount(StringRef EncodingString, 547 ArrayRef<yaml::Hex64> Values, 548 uint64_t ExpectedOperands) { 549 if (Values.size() != ExpectedOperands) 550 return createStringError( 551 errc::invalid_argument, 552 "invalid number (%zu) of operands for the operator: %s, %" PRIu64 553 " expected", 554 Values.size(), EncodingString.str().c_str(), ExpectedOperands); 555 556 return Error::success(); 557 } 558 559 static Error writeListEntryAddress(StringRef EncodingName, raw_ostream &OS, 560 uint64_t Addr, uint8_t AddrSize, 561 bool IsLittleEndian) { 562 if (Error Err = writeVariableSizedInteger(Addr, AddrSize, OS, IsLittleEndian)) 563 return createStringError(errc::invalid_argument, 564 "unable to write address for the operator %s: %s", 565 EncodingName.str().c_str(), 566 toString(std::move(Err)).c_str()); 567 568 return Error::success(); 569 } 570 571 static Expected<uint64_t> writeListEntry(raw_ostream &OS, 572 const DWARFYAML::RnglistEntry &Entry, 573 uint8_t AddrSize, 574 bool IsLittleEndian) { 575 uint64_t BeginOffset = OS.tell(); 576 writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian); 577 578 StringRef EncodingName = dwarf::RangeListEncodingString(Entry.Operator); 579 580 auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error { 581 return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands); 582 }; 583 584 auto WriteAddress = [&](uint64_t Addr) -> Error { 585 return writeListEntryAddress(EncodingName, OS, Addr, AddrSize, 586 IsLittleEndian); 587 }; 588 589 switch (Entry.Operator) { 590 case dwarf::DW_RLE_end_of_list: 591 if (Error Err = CheckOperands(0)) 592 return std::move(Err); 593 break; 594 case dwarf::DW_RLE_base_addressx: 595 if (Error Err = CheckOperands(1)) 596 return std::move(Err); 597 encodeULEB128(Entry.Values[0], OS); 598 break; 599 case dwarf::DW_RLE_startx_endx: 600 case dwarf::DW_RLE_startx_length: 601 case dwarf::DW_RLE_offset_pair: 602 if (Error Err = CheckOperands(2)) 603 return std::move(Err); 604 encodeULEB128(Entry.Values[0], OS); 605 encodeULEB128(Entry.Values[1], OS); 606 break; 607 case dwarf::DW_RLE_base_address: 608 if (Error Err = CheckOperands(1)) 609 return std::move(Err); 610 if (Error Err = WriteAddress(Entry.Values[0])) 611 return std::move(Err); 612 break; 613 case dwarf::DW_RLE_start_end: 614 if (Error Err = CheckOperands(2)) 615 return std::move(Err); 616 if (Error Err = WriteAddress(Entry.Values[0])) 617 return std::move(Err); 618 cantFail(WriteAddress(Entry.Values[1])); 619 break; 620 case dwarf::DW_RLE_start_length: 621 if (Error Err = CheckOperands(2)) 622 return std::move(Err); 623 if (Error Err = WriteAddress(Entry.Values[0])) 624 return std::move(Err); 625 encodeULEB128(Entry.Values[1], OS); 626 break; 627 } 628 629 return OS.tell() - BeginOffset; 630 } 631 632 template <typename EntryType> 633 Error writeDWARFLists(raw_ostream &OS, 634 ArrayRef<DWARFYAML::ListTable<EntryType>> Tables, 635 bool IsLittleEndian, bool Is64BitAddrSize) { 636 for (const DWARFYAML::ListTable<EntryType> &Table : Tables) { 637 // sizeof(version) + sizeof(address_size) + sizeof(segment_selector_size) + 638 // sizeof(offset_entry_count) = 8 639 uint64_t Length = 8; 640 641 uint8_t AddrSize; 642 if (Table.AddrSize) 643 AddrSize = *Table.AddrSize; 644 else 645 AddrSize = Is64BitAddrSize ? 8 : 4; 646 647 // Since the length of the current range/location lists entry is 648 // undetermined yet, we firstly write the content of the range/location 649 // lists to a buffer to calculate the length and then serialize the buffer 650 // content to the actual output stream. 651 std::string ListBuffer; 652 raw_string_ostream ListBufferOS(ListBuffer); 653 654 // Offsets holds offsets for each range/location list. The i-th element is 655 // the offset from the beginning of the first range/location list to the 656 // location of the i-th range list. 657 std::vector<uint64_t> Offsets; 658 659 for (const DWARFYAML::ListEntries<EntryType> &List : Table.Lists) { 660 Offsets.push_back(ListBufferOS.tell()); 661 if (List.Content) { 662 List.Content->writeAsBinary(ListBufferOS, UINT64_MAX); 663 Length += List.Content->binary_size(); 664 } else if (List.Entries) { 665 for (const EntryType &Entry : *List.Entries) { 666 Expected<uint64_t> EntrySize = 667 writeListEntry(ListBufferOS, Entry, AddrSize, IsLittleEndian); 668 if (!EntrySize) 669 return EntrySize.takeError(); 670 Length += *EntrySize; 671 } 672 } 673 } 674 675 // If the offset_entry_count field isn't specified, yaml2obj will infer it 676 // from the 'Offsets' field in the YAML description. If the 'Offsets' field 677 // isn't specified either, yaml2obj will infer it from the auto-generated 678 // offsets. 679 uint32_t OffsetEntryCount; 680 if (Table.OffsetEntryCount) 681 OffsetEntryCount = *Table.OffsetEntryCount; 682 else 683 OffsetEntryCount = Table.Offsets ? Table.Offsets->size() : Offsets.size(); 684 uint64_t OffsetsSize = 685 OffsetEntryCount * (Table.Format == dwarf::DWARF64 ? 8 : 4); 686 Length += OffsetsSize; 687 688 // If the length is specified in the YAML description, we use it instead of 689 // the actual length. 690 if (Table.Length) 691 Length = *Table.Length; 692 693 writeInitialLength(Table.Format, Length, OS, IsLittleEndian); 694 writeInteger((uint16_t)Table.Version, OS, IsLittleEndian); 695 writeInteger((uint8_t)AddrSize, OS, IsLittleEndian); 696 writeInteger((uint8_t)Table.SegSelectorSize, OS, IsLittleEndian); 697 writeInteger((uint32_t)OffsetEntryCount, OS, IsLittleEndian); 698 699 auto EmitOffsets = [&](ArrayRef<uint64_t> Offsets, uint64_t OffsetsSize) { 700 for (uint64_t Offset : Offsets) 701 writeDWARFOffset(OffsetsSize + Offset, Table.Format, OS, 702 IsLittleEndian); 703 }; 704 705 if (Table.Offsets) 706 EmitOffsets(ArrayRef<uint64_t>((const uint64_t *)Table.Offsets->data(), 707 Table.Offsets->size()), 708 0); 709 else 710 EmitOffsets(Offsets, OffsetsSize); 711 712 OS.write(ListBuffer.data(), ListBuffer.size()); 713 } 714 715 return Error::success(); 716 } 717 718 Error DWARFYAML::emitDebugRnglists(raw_ostream &OS, const Data &DI) { 719 assert(DI.DebugRnglists && "unexpected emitDebugRnglists() call"); 720 return writeDWARFLists<DWARFYAML::RnglistEntry>( 721 OS, *DI.DebugRnglists, DI.IsLittleEndian, DI.Is64BitAddrSize); 722 } 723 724 using EmitFuncType = Error (*)(raw_ostream &, const DWARFYAML::Data &); 725 726 static Error 727 emitDebugSectionImpl(const DWARFYAML::Data &DI, EmitFuncType EmitFunc, 728 StringRef Sec, 729 StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) { 730 std::string Data; 731 raw_string_ostream DebugInfoStream(Data); 732 if (Error Err = EmitFunc(DebugInfoStream, DI)) 733 return Err; 734 DebugInfoStream.flush(); 735 if (!Data.empty()) 736 OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data); 737 738 return Error::success(); 739 } 740 741 Expected<StringMap<std::unique_ptr<MemoryBuffer>>> 742 DWARFYAML::emitDebugSections(StringRef YAMLString, bool IsLittleEndian) { 743 auto CollectDiagnostic = [](const SMDiagnostic &Diag, void *DiagContext) { 744 *static_cast<SMDiagnostic *>(DiagContext) = Diag; 745 }; 746 747 SMDiagnostic GeneratedDiag; 748 yaml::Input YIn(YAMLString, /*Ctxt=*/nullptr, CollectDiagnostic, 749 &GeneratedDiag); 750 751 DWARFYAML::Data DI; 752 DI.IsLittleEndian = IsLittleEndian; 753 YIn >> DI; 754 if (YIn.error()) 755 return createStringError(YIn.error(), GeneratedDiag.getMessage()); 756 757 StringMap<std::unique_ptr<MemoryBuffer>> DebugSections; 758 Error Err = emitDebugSectionImpl(DI, &DWARFYAML::emitDebugInfo, "debug_info", 759 DebugSections); 760 Err = joinErrors(std::move(Err), 761 emitDebugSectionImpl(DI, &DWARFYAML::emitDebugLine, 762 "debug_line", DebugSections)); 763 Err = joinErrors(std::move(Err), 764 emitDebugSectionImpl(DI, &DWARFYAML::emitDebugStr, 765 "debug_str", DebugSections)); 766 Err = joinErrors(std::move(Err), 767 emitDebugSectionImpl(DI, &DWARFYAML::emitDebugAbbrev, 768 "debug_abbrev", DebugSections)); 769 Err = joinErrors(std::move(Err), 770 emitDebugSectionImpl(DI, &DWARFYAML::emitDebugAranges, 771 "debug_aranges", DebugSections)); 772 Err = joinErrors(std::move(Err), 773 emitDebugSectionImpl(DI, &DWARFYAML::emitDebugRanges, 774 "debug_ranges", DebugSections)); 775 776 if (Err) 777 return std::move(Err); 778 return std::move(DebugSections); 779 } 780