Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // -*- mode: C++ -*- | 1 // -*- mode: C++ -*- |
| 2 | 2 |
| 3 // Copyright (c) 2010 Google Inc. All Rights Reserved. | 3 // Copyright (c) 2010 Google Inc. All Rights Reserved. |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 40 #ifndef COMMON_DWARF_DWARF2READER_H__ | 40 #ifndef COMMON_DWARF_DWARF2READER_H__ |
| 41 #define COMMON_DWARF_DWARF2READER_H__ | 41 #define COMMON_DWARF_DWARF2READER_H__ |
| 42 | 42 |
| 43 #include <stdint.h> | 43 #include <stdint.h> |
| 44 | 44 |
| 45 #include <list> | 45 #include <list> |
| 46 #include <map> | 46 #include <map> |
| 47 #include <string> | 47 #include <string> |
| 48 #include <utility> | 48 #include <utility> |
| 49 #include <vector> | 49 #include <vector> |
| 50 #include <memory> | |
| 50 | 51 |
| 51 #include "common/dwarf/bytereader.h" | 52 #include "common/dwarf/bytereader.h" |
| 52 #include "common/dwarf/dwarf2enums.h" | 53 #include "common/dwarf/dwarf2enums.h" |
| 53 #include "common/dwarf/types.h" | 54 #include "common/dwarf/types.h" |
| 54 #include "common/using_std_string.h" | 55 #include "common/using_std_string.h" |
| 56 #include "common/dwarf/elf_reader.h" | |
| 55 | 57 |
| 56 namespace dwarf2reader { | 58 namespace dwarf2reader { |
| 57 struct LineStateMachine; | 59 struct LineStateMachine; |
| 58 class Dwarf2Handler; | 60 class Dwarf2Handler; |
| 59 class LineInfoHandler; | 61 class LineInfoHandler; |
| 62 class DwpReader; | |
| 60 | 63 |
| 61 // This maps from a string naming a section to a pair containing a | 64 // This maps from a string naming a section to a pair containing a |
| 62 // the data for the section, and the size of the section. | 65 // the data for the section, and the size of the section. |
| 63 typedef std::map<string, std::pair<const uint8_t *, uint64> > SectionMap; | 66 typedef std::map<string, std::pair<const uint8_t *, uint64> > SectionMap; |
| 64 typedef std::list<std::pair<enum DwarfAttribute, enum DwarfForm> > | 67 typedef std::list<std::pair<enum DwarfAttribute, enum DwarfForm> > |
| 65 AttributeList; | 68 AttributeList; |
| 66 typedef AttributeList::iterator AttributeIterator; | 69 typedef AttributeList::iterator AttributeIterator; |
| 67 typedef AttributeList::const_iterator ConstAttributeIterator; | 70 typedef AttributeList::const_iterator ConstAttributeIterator; |
| 68 | 71 |
| 69 struct LineInfoHeader { | 72 struct LineInfoHeader { |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 // Called when the line info reader has a new line, address pair | 180 // Called when the line info reader has a new line, address pair |
| 178 // ready for us. ADDRESS is the address of the code, LENGTH is the | 181 // ready for us. ADDRESS is the address of the code, LENGTH is the |
| 179 // length of its machine code in bytes, FILE_NUM is the file number | 182 // length of its machine code in bytes, FILE_NUM is the file number |
| 180 // containing the code, LINE_NUM is the line number in that file for | 183 // containing the code, LINE_NUM is the line number in that file for |
| 181 // the code, and COLUMN_NUM is the column number the code starts at, | 184 // the code, and COLUMN_NUM is the column number the code starts at, |
| 182 // if we know it (0 otherwise). | 185 // if we know it (0 otherwise). |
| 183 virtual void AddLine(uint64 address, uint64 length, | 186 virtual void AddLine(uint64 address, uint64 length, |
| 184 uint32 file_num, uint32 line_num, uint32 column_num) { } | 187 uint32 file_num, uint32 line_num, uint32 column_num) { } |
| 185 }; | 188 }; |
| 186 | 189 |
| 190 // This class is the main interface between the reader and the | |
| 191 // client. The virtual functions inside this get called for | |
| 192 // interesting events that happen during DWARF2 reading. | |
| 193 // The default implementation skips everything. | |
| 194 | |
|
ivanpe
2016/04/27 01:11:44
No need to leave a blank line.
yunlian
2016/04/27 16:35:29
Done.
| |
| 195 class Dwarf2Handler { | |
| 196 public: | |
| 197 Dwarf2Handler() { } | |
| 198 | |
| 199 virtual ~Dwarf2Handler() { } | |
| 200 | |
| 201 // Start to process a compilation unit at OFFSET from the beginning of the | |
|
ivanpe
2016/04/27 01:11:45
It looks like the code that follows comes from:
ht
| |
| 202 // .debug_info section. Return false if you would like to skip this | |
| 203 // compilation unit. | |
| 204 virtual bool StartCompilationUnit(uint64 offset, uint8 address_size, | |
| 205 uint8 offset_size, uint64 cu_length, | |
| 206 uint8 dwarf_version) { return false; } | |
| 207 | |
| 208 // When processing a skeleton compilation unit, resulting from a split | |
| 209 // DWARF compilation, once the skeleton debug info has been read, | |
| 210 // the reader will call this function to ask the client if it needs | |
| 211 // the full debug info from the .dwo or .dwp file. Return true if | |
| 212 // you need it, or false to skip processing the split debug info. | |
| 213 virtual bool NeedSplitDebugInfo() { return true; } | |
| 214 | |
| 215 // Start to process a split compilation unit at OFFSET from the beginning of | |
| 216 // the debug_info section in the .dwp/.dwo file. Return false if you would | |
| 217 // like to skip this compilation unit. | |
| 218 virtual bool StartSplitCompilationUnit(uint64 offset, | |
| 219 uint64 cu_length) { return false; } | |
| 220 | |
| 221 // Start to process a DIE at OFFSET from the beginning of the .debug_info | |
| 222 // section. Return false if you would like to skip this DIE. | |
| 223 virtual bool StartDIE(uint64 offset, enum DwarfTag tag) { return false; } | |
| 224 | |
| 225 // Called when we have an attribute with unsigned data to give to our | |
| 226 // handler. The attribute is for the DIE at OFFSET from the beginning of the | |
| 227 // .debug_info section. Its name is ATTR, its form is FORM, and its value is | |
| 228 // DATA. | |
| 229 virtual void ProcessAttributeUnsigned(uint64 offset, | |
| 230 enum DwarfAttribute attr, | |
| 231 enum DwarfForm form, | |
| 232 uint64 data) { } | |
| 233 | |
| 234 // Called when we have an attribute with signed data to give to our handler. | |
| 235 // The attribute is for the DIE at OFFSET from the beginning of the | |
| 236 // .debug_info section. Its name is ATTR, its form is FORM, and its value is | |
| 237 // DATA. | |
| 238 virtual void ProcessAttributeSigned(uint64 offset, | |
| 239 enum DwarfAttribute attr, | |
| 240 enum DwarfForm form, | |
| 241 int64 data) { } | |
| 242 | |
| 243 // Called when we have an attribute whose value is a reference to | |
|
ivanpe
2016/04/27 01:11:44
indent is off
yunlian
2016/04/27 16:35:29
Done.
| |
| 244 // another DIE. The attribute belongs to the DIE at OFFSET from the | |
| 245 // beginning of the .debug_info section. Its name is ATTR, its form | |
| 246 // is FORM, and the offset of the DIE being referred to from the | |
| 247 // beginning of the .debug_info section is DATA. | |
| 248 virtual void ProcessAttributeReference(uint64 offset, | |
| 249 enum DwarfAttribute attr, | |
| 250 enum DwarfForm form, | |
| 251 uint64 data) { } | |
| 252 | |
| 253 // Called when we have an attribute with a buffer of data to give to our | |
| 254 // handler. The attribute is for the DIE at OFFSET from the beginning of the | |
| 255 // .debug_info section. Its name is ATTR, its form is FORM, DATA points to | |
| 256 // the buffer's contents, and its length in bytes is LENGTH. The buffer is | |
| 257 // owned by the caller, not the callee, and may not persist for very long. | |
| 258 // If you want the data to be available later, it needs to be copied. | |
| 259 virtual void ProcessAttributeBuffer(uint64 offset, | |
| 260 enum DwarfAttribute attr, | |
| 261 enum DwarfForm form, | |
| 262 const uint8_t *data, | |
| 263 uint64 len) { } | |
| 264 | |
| 265 // Called when we have an attribute with string data to give to our handler. | |
| 266 // The attribute is for the DIE at OFFSET from the beginning of the | |
| 267 // .debug_info section. Its name is ATTR, its form is FORM, and its value is | |
| 268 // DATA. | |
| 269 virtual void ProcessAttributeString(uint64 offset, | |
| 270 enum DwarfAttribute attr, | |
| 271 enum DwarfForm form, | |
| 272 const string& data) { } | |
| 273 | |
| 274 // Called when we have an attribute whose value is the 64-bit signature | |
| 275 // of a type unit in the .debug_types section. OFFSET is the offset of | |
| 276 // the DIE whose attribute we're reporting. ATTR and FORM are the | |
| 277 // attribute's name and form. SIGNATURE is the type unit's signature. | |
| 278 virtual void ProcessAttributeSignature(uint64 offset, | |
| 279 enum DwarfAttribute attr, | |
| 280 enum DwarfForm form, | |
| 281 uint64 signature) { } | |
| 282 | |
| 283 // Called when finished processing the DIE at OFFSET. | |
| 284 // Because DWARF2/3 specifies a tree of DIEs, you may get starts | |
| 285 // before ends of the previous DIE, as we process children before | |
| 286 // ending the parent. | |
| 287 virtual void EndDIE(uint64 offset) { } | |
| 288 | |
| 289 }; | |
| 290 | |
| 187 // The base of DWARF2/3 debug info is a DIE (Debugging Information | 291 // The base of DWARF2/3 debug info is a DIE (Debugging Information |
| 188 // Entry. | 292 // Entry. |
| 189 // DWARF groups DIE's into a tree and calls the root of this tree a | 293 // DWARF groups DIE's into a tree and calls the root of this tree a |
| 190 // "compilation unit". Most of the time, there is one compilation | 294 // "compilation unit". Most of the time, there is one compilation |
| 191 // unit in the .debug_info section for each file that had debug info | 295 // unit in the .debug_info section for each file that had debug info |
| 192 // generated. | 296 // generated. |
| 193 // Each DIE consists of | 297 // Each DIE consists of |
| 194 | 298 |
| 195 // 1. a tag specifying a thing that is being described (ie | 299 // 1. a tag specifying a thing that is being described (ie |
| 196 // DW_TAG_subprogram for functions, DW_TAG_variable for variables, etc | 300 // DW_TAG_subprogram for functions, DW_TAG_variable for variables, etc |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 218 // units, such as base types, etc. GCC 3.4+ support this with | 322 // units, such as base types, etc. GCC 3.4+ support this with |
| 219 // -feliminate-dwarf2-dups. Other toolchains will sometimes do | 323 // -feliminate-dwarf2-dups. Other toolchains will sometimes do |
| 220 // duplicate elimination in the linker. | 324 // duplicate elimination in the linker. |
| 221 | 325 |
| 222 class CompilationUnit { | 326 class CompilationUnit { |
| 223 public: | 327 public: |
| 224 | 328 |
| 225 // Initialize a compilation unit. This requires a map of sections, | 329 // Initialize a compilation unit. This requires a map of sections, |
| 226 // the offset of this compilation unit in the .debug_info section, a | 330 // the offset of this compilation unit in the .debug_info section, a |
| 227 // ByteReader, and a Dwarf2Handler class to call callbacks in. | 331 // ByteReader, and a Dwarf2Handler class to call callbacks in. |
| 228 CompilationUnit(const SectionMap& sections, uint64 offset, | 332 CompilationUnit(const string& path, const SectionMap& sections, uint64 offset, |
| 229 ByteReader* reader, Dwarf2Handler* handler); | 333 ByteReader* reader, Dwarf2Handler* handler); |
| 230 virtual ~CompilationUnit() { | 334 virtual ~CompilationUnit() { |
| 231 if (abbrevs_) delete abbrevs_; | 335 if (abbrevs_) delete abbrevs_; |
| 232 } | 336 } |
| 233 | 337 |
| 338 // Initialize a compilation unit from a .dwo or .dwp file. | |
| 339 // In this case, we need the .debug_addr section from the | |
| 340 // executable file that contains the corresponding skeleton | |
| 341 // compilation unit. We also inherit the Dwarf2Handler from | |
| 342 // the executable file, and call it as if we were still | |
| 343 // processing the original compilation unit. | |
| 344 void SetSplitDwarf(const uint8_t* addr_buffer, uint64 addr_buffer_length, | |
| 345 uint64 addr_base, uint64 ranges_base, uint64 dwo_id); | |
| 346 | |
| 234 // Begin reading a Dwarf2 compilation unit, and calling the | 347 // Begin reading a Dwarf2 compilation unit, and calling the |
| 235 // callbacks in the Dwarf2Handler | 348 // callbacks in the Dwarf2Handler |
| 236 | 349 |
| 237 // Return the full length of the compilation unit, including | 350 // Return the full length of the compilation unit, including |
| 238 // headers. This plus the starting offset passed to the constructor | 351 // headers. This plus the starting offset passed to the constructor |
| 239 // is the offset of the end of the compilation unit --- and the | 352 // is the offset of the end of the compilation unit --- and the |
| 240 // start of the next compilation unit, if there is one. | 353 // start of the next compilation unit, if there is one. |
| 241 uint64 Start(); | 354 uint64 Start(); |
| 242 | 355 |
| 243 private: | 356 private: |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 274 const uint8_t *start, | 387 const uint8_t *start, |
| 275 const Abbrev& abbrev); | 388 const Abbrev& abbrev); |
| 276 | 389 |
| 277 // Processes a single attribute and return a new pointer just past the | 390 // Processes a single attribute and return a new pointer just past the |
| 278 // end of it | 391 // end of it |
| 279 const uint8_t *ProcessAttribute(uint64 dieoffset, | 392 const uint8_t *ProcessAttribute(uint64 dieoffset, |
| 280 const uint8_t *start, | 393 const uint8_t *start, |
| 281 enum DwarfAttribute attr, | 394 enum DwarfAttribute attr, |
| 282 enum DwarfForm form); | 395 enum DwarfForm form); |
| 283 | 396 |
| 397 // Called when we have an attribute with unsigned data to give to | |
| 398 // our handler. The attribute is for the DIE at OFFSET from the | |
| 399 // beginning of compilation unit, has a name of ATTR, a form of | |
| 400 // FORM, and the actual data of the attribute is in DATA. | |
| 401 // If we see a DW_AT_GNU_dwo_id attribute, save the value so that | |
| 402 // we can find the debug info in a .dwo or .dwp file. | |
| 403 void ProcessAttributeUnsigned(uint64 offset, | |
| 404 enum DwarfAttribute attr, | |
| 405 enum DwarfForm form, | |
| 406 uint64 data) { | |
| 407 if (attr == DW_AT_GNU_dwo_id) | |
|
ivanpe
2016/04/27 01:11:44
I would suggest to put curly braces around these.
yunlian
2016/04/27 16:35:29
Done.
| |
| 408 dwo_id_ = data; | |
| 409 else if (attr == DW_AT_GNU_addr_base) | |
| 410 addr_base_ = data; | |
| 411 else if (attr == DW_AT_GNU_ranges_base) | |
| 412 ranges_base_ = data; | |
| 413 // TODO(ccoutant): When we add DW_AT_ranges_base from DWARF-5, | |
|
ivanpe
2016/04/27 01:11:45
Why not TODO(yunlian): ?
yunlian
2016/04/27 16:35:29
Done.
| |
| 414 // that base will apply to DW_AT_ranges attributes in the | |
| 415 // skeleton CU as well as in the .dwo/.dwp files. | |
| 416 else if (attr == DW_AT_ranges && is_split_dwarf_) | |
| 417 data += ranges_base_; | |
| 418 handler_->ProcessAttributeUnsigned(offset, attr, form, data); | |
| 419 } | |
| 420 | |
| 421 // Called when we have an attribute with signed data to give to | |
| 422 // our handler. The attribute is for the DIE at OFFSET from the | |
| 423 // beginning of compilation unit, has a name of ATTR, a form of | |
| 424 // FORM, and the actual data of the attribute is in DATA. | |
| 425 void ProcessAttributeSigned(uint64 offset, | |
| 426 enum DwarfAttribute attr, | |
| 427 enum DwarfForm form, | |
| 428 int64 data) { | |
| 429 handler_->ProcessAttributeSigned(offset, attr, form, data); | |
| 430 } | |
| 431 | |
| 432 // Called when we have an attribute with a buffer of data to give to | |
| 433 // our handler. The attribute is for the DIE at OFFSET from the | |
| 434 // beginning of compilation unit, has a name of ATTR, a form of | |
| 435 // FORM, and the actual data of the attribute is in DATA, and the | |
| 436 // length of the buffer is LENGTH. | |
| 437 void ProcessAttributeBuffer(uint64 offset, | |
| 438 enum DwarfAttribute attr, | |
| 439 enum DwarfForm form, | |
| 440 const uint8_t* data, | |
| 441 uint64 len) { | |
| 442 handler_->ProcessAttributeBuffer(offset, attr, form, data, len); | |
| 443 } | |
| 444 | |
| 445 // Called when we have an attribute with string data to give to | |
| 446 // our handler. The attribute is for the DIE at OFFSET from the | |
| 447 // beginning of compilation unit, has a name of ATTR, a form of | |
| 448 // FORM, and the actual data of the attribute is in DATA. | |
| 449 // If we see a DW_AT_GNU_dwo_name attribute, save the value so | |
| 450 // that we can find the debug info in a .dwo or .dwp file. | |
| 451 void ProcessAttributeString(uint64 offset, | |
| 452 enum DwarfAttribute attr, | |
| 453 enum DwarfForm form, | |
| 454 const char* data) { | |
| 455 if (attr == DW_AT_GNU_dwo_name) | |
| 456 dwo_name_ = data; | |
| 457 handler_->ProcessAttributeString(offset, attr, form, data); | |
| 458 } | |
| 459 | |
| 284 // Processes all DIEs for this compilation unit | 460 // Processes all DIEs for this compilation unit |
| 285 void ProcessDIEs(); | 461 void ProcessDIEs(); |
| 286 | 462 |
| 287 // Skips the die with attributes specified in ABBREV starting at | 463 // Skips the die with attributes specified in ABBREV starting at |
| 288 // START, and return the new place to position the stream to. | 464 // START, and return the new place to position the stream to. |
| 289 const uint8_t *SkipDIE(const uint8_t *start, const Abbrev& abbrev); | 465 const uint8_t *SkipDIE(const uint8_t *start, const Abbrev& abbrev); |
| 290 | 466 |
| 291 // Skips the attribute starting at START, with FORM, and return the | 467 // Skips the attribute starting at START, with FORM, and return the |
| 292 // new place to position the stream to. | 468 // new place to position the stream to. |
| 293 const uint8_t *SkipAttribute(const uint8_t *start, enum DwarfForm form); | 469 const uint8_t *SkipAttribute(const uint8_t *start, enum DwarfForm form); |
| 294 | 470 |
| 471 // Process the actual debug information in a split DWARF file. | |
| 472 void ProcessSplitDwarf(); | |
| 473 | |
| 474 // Read the debug sections from a .dwo file. | |
| 475 void ReadDebugSectionsFromDwo(ElfReader* elf_reader, | |
| 476 SectionMap* sections); | |
| 477 | |
| 478 // Path of the file containing the debug information. | |
| 479 const string path_; | |
| 480 | |
| 295 // Offset from section start is the offset of this compilation unit | 481 // Offset from section start is the offset of this compilation unit |
| 296 // from the beginning of the .debug_info section. | 482 // from the beginning of the .debug_info section. |
| 297 uint64 offset_from_section_start_; | 483 uint64 offset_from_section_start_; |
| 298 | 484 |
| 299 // buffer is the buffer for our CU, starting at .debug_info + offset | 485 // buffer is the buffer for our CU, starting at .debug_info + offset |
| 300 // passed in from constructor. | 486 // passed in from constructor. |
| 301 // after_header points to right after the compilation unit header. | 487 // after_header points to right after the compilation unit header. |
| 302 const uint8_t *buffer_; | 488 const uint8_t *buffer_; |
| 303 uint64 buffer_length_; | 489 uint64 buffer_length_; |
| 304 const uint8_t *after_header_; | 490 const uint8_t *after_header_; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 315 // Set of DWARF2/3 abbreviations for this compilation unit. Indexed | 501 // Set of DWARF2/3 abbreviations for this compilation unit. Indexed |
| 316 // by abbreviation number, which means that abbrevs_[0] is not | 502 // by abbreviation number, which means that abbrevs_[0] is not |
| 317 // valid. | 503 // valid. |
| 318 std::vector<Abbrev>* abbrevs_; | 504 std::vector<Abbrev>* abbrevs_; |
| 319 | 505 |
| 320 // String section buffer and length, if we have a string section. | 506 // String section buffer and length, if we have a string section. |
| 321 // This is here to avoid doing a section lookup for strings in | 507 // This is here to avoid doing a section lookup for strings in |
| 322 // ProcessAttribute, which is in the hot path for DWARF2 reading. | 508 // ProcessAttribute, which is in the hot path for DWARF2 reading. |
| 323 const uint8_t *string_buffer_; | 509 const uint8_t *string_buffer_; |
| 324 uint64 string_buffer_length_; | 510 uint64 string_buffer_length_; |
| 511 | |
| 512 // String offsets section buffer and length, if we have a string offsets | |
| 513 // section (.debug_str_offsets or .debug_str_offsets.dwo). | |
| 514 const uint8_t* str_offsets_buffer_; | |
| 515 uint64 str_offsets_buffer_length_; | |
| 516 | |
| 517 // Address section buffer and length, if we have an address section | |
| 518 // (.debug_addr). | |
| 519 const uint8_t* addr_buffer_; | |
| 520 uint64 addr_buffer_length_; | |
| 521 | |
| 522 // Flag indicating whether this compilation unit is part of a .dwo | |
| 523 // or .dwp file. If true, we are reading this unit because a | |
| 524 // skeleton compilation unit in an executable file had a | |
| 525 // DW_AT_GNU_dwo_name or DW_AT_GNU_dwo_id attribute. | |
| 526 // In a .dwo file, we expect the string offsets section to | |
| 527 // have a ".dwo" suffix, and we will use the ".debug_addr" section | |
| 528 // associated with the skeleton compilation unit. | |
| 529 bool is_split_dwarf_; | |
| 530 | |
| 531 // The value of the DW_AT_GNU_dwo_id attribute, if any. | |
| 532 uint64 dwo_id_; | |
| 533 | |
| 534 // The value of the DW_AT_GNU_dwo_name attribute, if any. | |
| 535 const char* dwo_name_; | |
| 536 | |
| 537 // If this is a split DWARF CU, the value of the DW_AT_GNU_dwo_id attribute | |
| 538 // from the skeleton CU. | |
| 539 uint64 skeleton_dwo_id_; | |
| 540 | |
| 541 // The value of the DW_AT_GNU_ranges_base attribute, if any. | |
| 542 uint64 ranges_base_; | |
| 543 | |
| 544 // The value of the DW_AT_GNU_addr_base attribute, if any. | |
| 545 uint64 addr_base_; | |
| 546 | |
| 547 // True if we have already looked for a .dwp file. | |
| 548 bool have_checked_for_dwp_; | |
| 549 | |
| 550 // Path to the .dwp file. | |
| 551 string dwp_path_; | |
| 552 | |
| 553 // ByteReader for the DWP file. | |
| 554 std::unique_ptr<ByteReader> dwp_byte_reader_; | |
| 555 | |
| 556 // DWP reader. | |
| 557 std::unique_ptr<DwpReader> dwp_reader_; | |
| 325 }; | 558 }; |
| 326 | 559 |
| 327 // This class is the main interface between the reader and the | 560 // A Reader for a .dwp file. Supports the fetching of DWARF debug |
| 328 // client. The virtual functions inside this get called for | 561 // info for a given dwo_id. |
| 329 // interesting events that happen during DWARF2 reading. | 562 // |
| 330 // The default implementation skips everything. | 563 // There are two versions of .dwp files. In both versions, the |
| 564 // .dwp file is an ELF file containing only debug sections. | |
| 565 // In Version 1, the file contains many copies of each debug | |
| 566 // section, one for each .dwo file that is packaged in the .dwp | |
| 567 // file, and the .debug_cu_index section maps from the dwo_id | |
| 568 // to a set of section indexes. In Version 2, the file contains | |
| 569 // one of each debug section, and the .debug_cu_index section | |
| 570 // maps from the dwo_id to a set of offsets and lengths that | |
| 571 // identify each .dwo file's contribution to the larger sections. | |
| 331 | 572 |
| 332 class Dwarf2Handler { | 573 class DwpReader { |
| 333 public: | 574 public: |
| 334 Dwarf2Handler() { } | 575 DwpReader(const ByteReader& byte_reader, ElfReader* elf_reader); |
| 335 | 576 |
| 336 virtual ~Dwarf2Handler() { } | 577 ~DwpReader(); |
| 337 | 578 |
| 338 // Start to process a compilation unit at OFFSET from the beginning of the | 579 // Read the CU index and initialize data members. |
| 339 // .debug_info section. Return false if you would like to skip this | 580 void Initialize(); |
| 340 // compilation unit. | |
| 341 virtual bool StartCompilationUnit(uint64 offset, uint8 address_size, | |
| 342 uint8 offset_size, uint64 cu_length, | |
| 343 uint8 dwarf_version) { return false; } | |
| 344 | 581 |
| 345 // Start to process a DIE at OFFSET from the beginning of the .debug_info | 582 // Read the debug sections for the given dwo_id. |
| 346 // section. Return false if you would like to skip this DIE. | 583 void ReadDebugSectionsForCU(uint64 dwo_id, SectionMap* sections); |
| 347 virtual bool StartDIE(uint64 offset, enum DwarfTag tag) { return false; } | |
| 348 | 584 |
| 349 // Called when we have an attribute with unsigned data to give to our | 585 private: |
| 350 // handler. The attribute is for the DIE at OFFSET from the beginning of the | 586 // Search a v1 hash table for "dwo_id". Returns the slot index |
| 351 // .debug_info section. Its name is ATTR, its form is FORM, and its value is | 587 // where the dwo_id was found, or -1 if it was not found. |
| 352 // DATA. | 588 int LookupCU(uint64 dwo_id); |
| 353 virtual void ProcessAttributeUnsigned(uint64 offset, | |
| 354 enum DwarfAttribute attr, | |
| 355 enum DwarfForm form, | |
| 356 uint64 data) { } | |
| 357 | 589 |
| 358 // Called when we have an attribute with signed data to give to our handler. | 590 // Search a v2 hash table for "dwo_id". Returns the row index |
| 359 // The attribute is for the DIE at OFFSET from the beginning of the | 591 // in the offsets and sizes tables, or 0 if it was not found. |
| 360 // .debug_info section. Its name is ATTR, its form is FORM, and its value is | 592 uint32 LookupCUv2(uint64 dwo_id); |
| 361 // DATA. | |
| 362 virtual void ProcessAttributeSigned(uint64 offset, | |
| 363 enum DwarfAttribute attr, | |
| 364 enum DwarfForm form, | |
| 365 int64 data) { } | |
| 366 | 593 |
| 367 // Called when we have an attribute whose value is a reference to | 594 // The ELF reader for the .dwp file. |
| 368 // another DIE. The attribute belongs to the DIE at OFFSET from the | 595 ElfReader* elf_reader_; |
| 369 // beginning of the .debug_info section. Its name is ATTR, its form | |
| 370 // is FORM, and the offset of the DIE being referred to from the | |
| 371 // beginning of the .debug_info section is DATA. | |
| 372 virtual void ProcessAttributeReference(uint64 offset, | |
| 373 enum DwarfAttribute attr, | |
| 374 enum DwarfForm form, | |
| 375 uint64 data) { } | |
| 376 | 596 |
| 377 // Called when we have an attribute with a buffer of data to give to our | 597 // The ByteReader for the .dwp file. |
| 378 // handler. The attribute is for the DIE at OFFSET from the beginning of the | 598 const ByteReader& byte_reader_; |
| 379 // .debug_info section. Its name is ATTR, its form is FORM, DATA points to | |
| 380 // the buffer's contents, and its length in bytes is LENGTH. The buffer is | |
| 381 // owned by the caller, not the callee, and may not persist for very long. | |
| 382 // If you want the data to be available later, it needs to be copied. | |
| 383 virtual void ProcessAttributeBuffer(uint64 offset, | |
| 384 enum DwarfAttribute attr, | |
| 385 enum DwarfForm form, | |
| 386 const uint8_t *data, | |
| 387 uint64 len) { } | |
| 388 | 599 |
| 389 // Called when we have an attribute with string data to give to our handler. | 600 // Pointer to the .debug_cu_index section. |
| 390 // The attribute is for the DIE at OFFSET from the beginning of the | 601 const char* cu_index_; |
| 391 // .debug_info section. Its name is ATTR, its form is FORM, and its value is | |
| 392 // DATA. | |
| 393 virtual void ProcessAttributeString(uint64 offset, | |
| 394 enum DwarfAttribute attr, | |
| 395 enum DwarfForm form, | |
| 396 const string& data) { } | |
| 397 | 602 |
| 398 // Called when we have an attribute whose value is the 64-bit signature | 603 // Size of the .debug_cu_index section. |
| 399 // of a type unit in the .debug_types section. OFFSET is the offset of | 604 size_t cu_index_size_; |
| 400 // the DIE whose attribute we're reporting. ATTR and FORM are the | |
| 401 // attribute's name and form. SIGNATURE is the type unit's signature. | |
| 402 virtual void ProcessAttributeSignature(uint64 offset, | |
| 403 enum DwarfAttribute attr, | |
| 404 enum DwarfForm form, | |
| 405 uint64 signature) { } | |
| 406 | 605 |
| 407 // Called when finished processing the DIE at OFFSET. | 606 // Pointer to the .debug_str.dwo section. |
| 408 // Because DWARF2/3 specifies a tree of DIEs, you may get starts | 607 const char* string_buffer_; |
| 409 // before ends of the previous DIE, as we process children before | |
| 410 // ending the parent. | |
| 411 virtual void EndDIE(uint64 offset) { } | |
| 412 | 608 |
| 609 // Size of the .debug_str.dwo section. | |
| 610 size_t string_buffer_size_; | |
| 611 | |
| 612 // Version of the .dwp file. We support versions 1 and 2 currently. | |
| 613 int version_; | |
| 614 | |
| 615 // Number of columns in the section tables (version 2). | |
| 616 unsigned int ncolumns_; | |
| 617 | |
| 618 // Number of units in the section tables (version 2). | |
| 619 unsigned int nunits_; | |
| 620 | |
| 621 // Number of slots in the hash table. | |
| 622 unsigned int nslots_; | |
| 623 | |
| 624 // Pointer to the beginning of the hash table. | |
| 625 const char* phash_; | |
| 626 | |
| 627 // Pointer to the beginning of the index table. | |
| 628 const char* pindex_; | |
| 629 | |
| 630 // Pointer to the beginning of the section index pool (version 1). | |
| 631 const char* shndx_pool_; | |
| 632 | |
| 633 // Pointer to the beginning of the section offset table (version 2). | |
| 634 const char* offset_table_; | |
| 635 | |
| 636 // Pointer to the beginning of the section size table (version 2). | |
| 637 const char* size_table_; | |
| 638 | |
| 639 // Contents of the sections of interest (version 2). | |
| 640 const char* abbrev_data_; | |
| 641 size_t abbrev_size_; | |
| 642 const char* info_data_; | |
| 643 size_t info_size_; | |
| 644 const char* str_offsets_data_; | |
| 645 size_t str_offsets_size_; | |
| 413 }; | 646 }; |
| 414 | 647 |
| 415 // This class is a reader for DWARF's Call Frame Information. CFI | 648 // This class is a reader for DWARF's Call Frame Information. CFI |
| 416 // describes how to unwind stack frames --- even for functions that do | 649 // describes how to unwind stack frames --- even for functions that do |
| 417 // not follow fixed conventions for saving registers, whose frame size | 650 // not follow fixed conventions for saving registers, whose frame size |
| 418 // varies as they execute, etc. | 651 // varies as they execute, etc. |
| 419 // | 652 // |
| 420 // CFI describes, at each machine instruction, how to compute the | 653 // CFI describes, at each machine instruction, how to compute the |
| 421 // stack frame's base address, how to find the return address, and | 654 // stack frame's base address, how to find the return address, and |
| 422 // where to find the saved values of the caller's registers (if the | 655 // where to find the saved values of the caller's registers (if the |
| (...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1043 // The name of the file whose CFI we're reading. | 1276 // The name of the file whose CFI we're reading. |
| 1044 string filename_; | 1277 string filename_; |
| 1045 | 1278 |
| 1046 // The name of the CFI section in that file. | 1279 // The name of the CFI section in that file. |
| 1047 string section_; | 1280 string section_; |
| 1048 }; | 1281 }; |
| 1049 | 1282 |
| 1050 } // namespace dwarf2reader | 1283 } // namespace dwarf2reader |
| 1051 | 1284 |
| 1052 #endif // UTIL_DEBUGINFO_DWARF2READER_H__ | 1285 #endif // UTIL_DEBUGINFO_DWARF2READER_H__ |
| OLD | NEW |