proxygen
folly::symbolizer::Dwarf::LineNumberVM Class Reference

Classes

struct  FileName
 

Public Member Functions

 LineNumberVM (folly::StringPiece data, folly::StringPiece compilationDirectory)
 
bool findAddress (uintptr_t address, Path &file, uint64_t &line)
 

Private Types

enum  StepResult { CONTINUE, COMMIT, END }
 

Private Member Functions

void init ()
 
void reset ()
 
bool next (folly::StringPiece &program)
 
StepResult step (folly::StringPiece &program)
 
FileName getFileName (uint64_t index) const
 
folly::StringPiece getIncludeDirectory (uint64_t index) const
 
bool nextDefineFile (folly::StringPiece &program, FileName &fn) const
 

Static Private Member Functions

static bool readFileName (folly::StringPiece &sp, FileName &fn)
 

Private Attributes

bool is64Bit_
 
folly::StringPiece data_
 
folly::StringPiece compilationDirectory_
 
uint16_t version_
 
uint8_t minLength_
 
bool defaultIsStmt_
 
int8_t lineBase_
 
uint8_t lineRange_
 
uint8_t opcodeBase_
 
const uint8_tstandardOpcodeLengths_
 
folly::StringPiece includeDirectories_
 
size_t includeDirectoryCount_
 
folly::StringPiece fileNames_
 
size_t fileNameCount_
 
uint64_t address_
 
uint64_t file_
 
uint64_t line_
 
uint64_t column_
 
bool isStmt_
 
bool basicBlock_
 
bool endSequence_
 
bool prologueEnd_
 
bool epilogueBegin_
 
uint64_t isa_
 
uint64_t discriminator_
 

Detailed Description

Definition at line 187 of file Dwarf.h.

Member Enumeration Documentation

Enumerator
CONTINUE 
COMMIT 
END 

Definition at line 201 of file Dwarf.h.

201  {
202  CONTINUE, // Continue feeding opcodes
203  COMMIT, // Commit new <address, file, line> tuple
204  END, // End of sequence
205  };

Constructor & Destructor Documentation

folly::symbolizer::Dwarf::LineNumberVM::LineNumberVM ( folly::StringPiece  data,
folly::StringPiece  compilationDirectory 
)

Definition at line 620 of file Dwarf.cpp.

References data_, FOLLY_SAFE_CHECK, init(), folly::symbolizer::Dwarf::Section::is64Bit(), is64Bit_, folly::symbolizer::Dwarf::Section::next(), and reset().

623  : compilationDirectory_(compilationDirectory) {
624  Section section(data);
625  FOLLY_SAFE_CHECK(section.next(data_), "invalid line number VM");
626  is64Bit_ = section.is64Bit();
627  init();
628  reset();
629 }
#define FOLLY_SAFE_CHECK(expr, msg)
Definition: SafeAssert.h:35
folly::StringPiece compilationDirectory_
Definition: Dwarf.h:233

Member Function Documentation

bool folly::symbolizer::Dwarf::LineNumberVM::findAddress ( uintptr_t  address,
Path file,
uint64_t line 
)

Definition at line 906 of file Dwarf.cpp.

References address_, compilationDirectory_, data_, folly::Range< Iter >::empty(), file_, getFileName(), getIncludeDirectory(), line_, next(), reset(), and uint64_t.

Referenced by folly::symbolizer::Dwarf::findLocation().

909  {
910  folly::StringPiece program = data_;
911 
912  // Within each sequence of instructions, the address may only increase.
913  // Unfortunately, within the same compilation unit, sequences may appear
914  // in any order. So any sequence is a candidate if it starts at an address
915  // <= the target address, and we know we've found the target address if
916  // a candidate crosses the target address.
917  enum State {
918  START,
919  LOW_SEQ, // candidate
920  HIGH_SEQ
921  };
922  State state = START;
923  reset();
924 
925  uint64_t prevFile = 0;
926  uint64_t prevLine = 0;
927  while (!program.empty()) {
928  bool seqEnd = !next(program);
929 
930  if (state == START) {
931  if (!seqEnd) {
932  state = address_ <= target ? LOW_SEQ : HIGH_SEQ;
933  }
934  }
935 
936  if (state == LOW_SEQ) {
937  if (address_ > target) {
938  // Found it! Note that ">" is indeed correct (not ">="), as each
939  // sequence is guaranteed to have one entry past-the-end (emitted by
940  // DW_LNE_end_sequence)
941  if (prevFile == 0) {
942  return false;
943  }
944  auto fn = getFileName(prevFile);
945  file = Path(
947  getIncludeDirectory(fn.directoryIndex),
948  fn.relativeName);
949  line = prevLine;
950  return true;
951  }
952  prevFile = file_;
953  prevLine = line_;
954  }
955 
956  if (seqEnd) {
957  state = START;
958  reset();
959  }
960  }
961 
962  return false;
963 }
bool next(folly::StringPiece &program)
Definition: Dwarf.cpp:688
constexpr bool empty() const
Definition: Range.h:443
State
See Core for details.
Definition: Core.h:43
folly::StringPiece getIncludeDirectory(uint64_t index) const
Definition: Dwarf.cpp:722
FileName getFileName(uint64_t index) const
Definition: Dwarf.cpp:697
state
Definition: http_parser.c:272
folly::StringPiece compilationDirectory_
Definition: Dwarf.h:233
Dwarf::LineNumberVM::FileName folly::symbolizer::Dwarf::LineNumberVM::getFileName ( uint64_t  index) const
private

Definition at line 697 of file Dwarf.cpp.

References data_, fileNameCount_, fileNames_, FOLLY_SAFE_CHECK, nextDefineFile(), and readFileName().

Referenced by findAddress().

698  {
699  FOLLY_SAFE_CHECK(index != 0, "invalid file index 0");
700 
701  FileName fn;
702  if (index <= fileNameCount_) {
703  folly::StringPiece fileNames = fileNames_;
704  for (; index; --index) {
705  if (!readFileName(fileNames, fn)) {
706  abort();
707  }
708  }
709  return fn;
710  }
711 
712  index -= fileNameCount_;
713 
714  folly::StringPiece program = data_;
715  for (; index; --index) {
716  FOLLY_SAFE_CHECK(nextDefineFile(program, fn), "invalid file index");
717  }
718 
719  return fn;
720 }
bool nextDefineFile(folly::StringPiece &program, FileName &fn) const
Definition: Dwarf.cpp:757
#define FOLLY_SAFE_CHECK(expr, msg)
Definition: SafeAssert.h:35
folly::StringPiece fileNames_
Definition: Dwarf.h:247
static bool readFileName(folly::StringPiece &sp, FileName &fn)
Definition: Dwarf.cpp:743
folly::StringPiece folly::symbolizer::Dwarf::LineNumberVM::getIncludeDirectory ( uint64_t  index) const
private

Definition at line 722 of file Dwarf.cpp.

References folly::Range< Iter >::empty(), FOLLY_SAFE_CHECK, includeDirectories_, and includeDirectoryCount_.

Referenced by findAddress().

723  {
724  if (index == 0) {
725  return folly::StringPiece();
726  }
727 
729  index <= includeDirectoryCount_, "invalid include directory");
730 
731  folly::StringPiece includeDirectories = includeDirectories_;
732  folly::StringPiece dir;
733  for (; index; --index) {
734  dir = readNullTerminated(includeDirectories);
735  if (dir.empty()) {
736  abort(); // BUG
737  }
738  }
739 
740  return dir;
741 }
constexpr bool empty() const
Definition: Range.h:443
folly::StringPiece includeDirectories_
Definition: Dwarf.h:244
#define FOLLY_SAFE_CHECK(expr, msg)
Definition: SafeAssert.h:35
Range< const char * > StringPiece
void folly::symbolizer::Dwarf::LineNumberVM::init ( )
private

Definition at line 645 of file Dwarf.cpp.

References folly::Range< Iter >::assign(), folly::Range< Iter >::data(), data_, defaultIsStmt_, folly::empty(), folly::Range< Iter >::end(), fileNameCount_, fileNames_, FOLLY_SAFE_CHECK, includeDirectories_, includeDirectoryCount_, is64Bit_, lineBase_, lineRange_, minLength_, opcodeBase_, readFileName(), folly::Range< Iter >::size(), standardOpcodeLengths_, uint64_t, uint8_t, and version_.

Referenced by LineNumberVM().

645  {
646  version_ = read<uint16_t>(data_);
648  version_ >= 2 && version_ <= 4, "invalid version in line number VM");
649  uint64_t headerLength = readOffset(data_, is64Bit_);
651  headerLength <= data_.size(), "invalid line number VM header length");
652  folly::StringPiece header(data_.data(), headerLength);
653  data_.assign(header.end(), data_.end());
654 
655  minLength_ = read<uint8_t>(header);
656  if (version_ == 4) { // Version 2 and 3 records don't have this
657  uint8_t maxOpsPerInstruction = read<uint8_t>(header);
658  FOLLY_SAFE_CHECK(maxOpsPerInstruction == 1, "VLIW not supported");
659  }
660  defaultIsStmt_ = read<uint8_t>(header);
661  lineBase_ = read<int8_t>(header); // yes, signed
662  lineRange_ = read<uint8_t>(header);
663  opcodeBase_ = read<uint8_t>(header);
664  FOLLY_SAFE_CHECK(opcodeBase_ != 0, "invalid opcode base");
665  standardOpcodeLengths_ = reinterpret_cast<const uint8_t*>(header.data());
666  header.advance(opcodeBase_ - 1);
667 
668  // We don't want to use heap, so we don't keep an unbounded amount of state.
669  // We'll just skip over include directories and file names here, and
670  // we'll loop again when we actually need to retrieve one.
672  const char* tmp = header.data();
674  while (!(sp = readNullTerminated(header)).empty()) {
676  }
677  includeDirectories_.assign(tmp, header.data());
678 
679  tmp = header.data();
680  FileName fn;
681  fileNameCount_ = 0;
682  while (readFileName(header, fn)) {
683  ++fileNameCount_;
684  }
685  fileNames_.assign(tmp, header.data());
686 }
constexpr size_type size() const
Definition: Range.h:431
const uint8_t * standardOpcodeLengths_
Definition: Dwarf.h:242
constexpr auto empty(C const &c) -> decltype(c.empty())
Definition: Access.h:55
constexpr Iter data() const
Definition: Range.h:446
void assign(Iter start, Iter end)
Definition: Range.h:416
folly::StringPiece includeDirectories_
Definition: Dwarf.h:244
#define FOLLY_SAFE_CHECK(expr, msg)
Definition: SafeAssert.h:35
constexpr Iter end() const
Definition: Range.h:455
folly::StringPiece fileNames_
Definition: Dwarf.h:247
static bool readFileName(folly::StringPiece &sp, FileName &fn)
Definition: Dwarf.cpp:743
bool folly::symbolizer::Dwarf::LineNumberVM::next ( folly::StringPiece program)
private

Definition at line 688 of file Dwarf.cpp.

References COMMIT, CONTINUE, and step().

Referenced by findAddress().

688  {
690  do {
691  ret = step(program);
692  } while (ret == CONTINUE);
693 
694  return (ret == COMMIT);
695 }
StepResult step(folly::StringPiece &program)
Definition: Dwarf.cpp:797
bool folly::symbolizer::Dwarf::LineNumberVM::nextDefineFile ( folly::StringPiece program,
FileName fn 
) const
private

Definition at line 757 of file Dwarf.cpp.

References folly::Range< Iter >::advance(), folly::Range< Iter >::empty(), FOLLY_SAFE_CHECK, opcodeBase_, readFileName(), standardOpcodeLengths_, and uint8_t.

Referenced by getFileName().

759  {
760  while (!program.empty()) {
761  auto opcode = read<uint8_t>(program);
762 
763  if (opcode >= opcodeBase_) { // special opcode
764  continue;
765  }
766 
767  if (opcode != 0) { // standard opcode
768  // Skip, slurp the appropriate number of LEB arguments
769  uint8_t argCount = standardOpcodeLengths_[opcode - 1];
770  while (argCount--) {
771  readULEB(program);
772  }
773  continue;
774  }
775 
776  // Extended opcode
777  auto length = readULEB(program);
778  // the opcode itself should be included in the length, so length >= 1
779  FOLLY_SAFE_CHECK(length != 0, "invalid extended opcode length");
780  read<uint8_t>(program); // extended opcode
781  --length;
782 
783  if (opcode == DW_LNE_define_file) {
785  readFileName(program, fn),
786  "invalid empty file in DW_LNE_define_file");
787  return true;
788  }
789 
790  program.advance(length);
791  continue;
792  }
793 
794  return false;
795 }
void advance(size_type n)
Definition: Range.h:672
const uint8_t * standardOpcodeLengths_
Definition: Dwarf.h:242
constexpr bool empty() const
Definition: Range.h:443
#define FOLLY_SAFE_CHECK(expr, msg)
Definition: SafeAssert.h:35
static bool readFileName(folly::StringPiece &sp, FileName &fn)
Definition: Dwarf.cpp:743
bool folly::symbolizer::Dwarf::LineNumberVM::readFileName ( folly::StringPiece sp,
FileName fn 
)
staticprivate

Definition at line 743 of file Dwarf.cpp.

References folly::symbolizer::Dwarf::LineNumberVM::FileName::directoryIndex, folly::Range< Iter >::empty(), and folly::symbolizer::Dwarf::LineNumberVM::FileName::relativeName.

Referenced by getFileName(), init(), and nextDefineFile().

745  {
746  fn.relativeName = readNullTerminated(program);
747  if (fn.relativeName.empty()) {
748  return false;
749  }
750  fn.directoryIndex = readULEB(program);
751  // Skip over file size and last modified time
752  readULEB(program);
753  readULEB(program);
754  return true;
755 }
void folly::symbolizer::Dwarf::LineNumberVM::reset ( )
private

Definition at line 631 of file Dwarf.cpp.

References address_, basicBlock_, column_, defaultIsStmt_, discriminator_, endSequence_, epilogueBegin_, file_, isa_, isStmt_, line_, and prologueEnd_.

Referenced by findAddress(), and LineNumberVM().

Dwarf::LineNumberVM::StepResult folly::symbolizer::Dwarf::LineNumberVM::step ( folly::StringPiece program)
private

Definition at line 797 of file Dwarf.cpp.

References address_, folly::Range< Iter >::advance(), basicBlock_, column_, COMMIT, CONTINUE, discriminator_, END, epilogueBegin_, file_, FOLLY_SAFE_CHECK, isa_, isStmt_, line_, lineBase_, lineRange_, minLength_, opcodeBase_, prologueEnd_, standardOpcodeLengths_, uint8_t, and version_.

Referenced by next().

798  {
799  auto opcode = read<uint8_t>(program);
800 
801  if (opcode >= opcodeBase_) { // special opcode
802  uint8_t adjustedOpcode = opcode - opcodeBase_;
803  uint8_t opAdvance = adjustedOpcode / lineRange_;
804 
805  address_ += minLength_ * opAdvance;
806  line_ += lineBase_ + adjustedOpcode % lineRange_;
807 
808  basicBlock_ = false;
809  prologueEnd_ = false;
810  epilogueBegin_ = false;
811  discriminator_ = 0;
812  return COMMIT;
813  }
814 
815  if (opcode != 0) { // standard opcode
816  // Only interpret opcodes that are recognized by the version we're parsing;
817  // the others are vendor extensions and we should ignore them.
818  switch (opcode) {
819  case DW_LNS_copy:
820  basicBlock_ = false;
821  prologueEnd_ = false;
822  epilogueBegin_ = false;
823  discriminator_ = 0;
824  return COMMIT;
825  case DW_LNS_advance_pc:
826  address_ += minLength_ * readULEB(program);
827  return CONTINUE;
828  case DW_LNS_advance_line:
829  line_ += readSLEB(program);
830  return CONTINUE;
831  case DW_LNS_set_file:
832  file_ = readULEB(program);
833  return CONTINUE;
834  case DW_LNS_set_column:
835  column_ = readULEB(program);
836  return CONTINUE;
837  case DW_LNS_negate_stmt:
838  isStmt_ = !isStmt_;
839  return CONTINUE;
840  case DW_LNS_set_basic_block:
841  basicBlock_ = true;
842  return CONTINUE;
843  case DW_LNS_const_add_pc:
844  address_ += minLength_ * ((255 - opcodeBase_) / lineRange_);
845  return CONTINUE;
846  case DW_LNS_fixed_advance_pc:
847  address_ += read<uint16_t>(program);
848  return CONTINUE;
849  case DW_LNS_set_prologue_end:
850  if (version_ == 2) {
851  break; // not supported in version 2
852  }
853  prologueEnd_ = true;
854  return CONTINUE;
855  case DW_LNS_set_epilogue_begin:
856  if (version_ == 2) {
857  break; // not supported in version 2
858  }
859  epilogueBegin_ = true;
860  return CONTINUE;
861  case DW_LNS_set_isa:
862  if (version_ == 2) {
863  break; // not supported in version 2
864  }
865  isa_ = readULEB(program);
866  return CONTINUE;
867  }
868 
869  // Unrecognized standard opcode, slurp the appropriate number of LEB
870  // arguments.
871  uint8_t argCount = standardOpcodeLengths_[opcode - 1];
872  while (argCount--) {
873  readULEB(program);
874  }
875  return CONTINUE;
876  }
877 
878  // Extended opcode
879  auto length = readULEB(program);
880  // the opcode itself should be included in the length, so length >= 1
881  FOLLY_SAFE_CHECK(length != 0, "invalid extended opcode length");
882  auto extendedOpcode = read<uint8_t>(program);
883  --length;
884 
885  switch (extendedOpcode) {
886  case DW_LNE_end_sequence:
887  return END;
888  case DW_LNE_set_address:
889  address_ = read<uintptr_t>(program);
890  return CONTINUE;
891  case DW_LNE_define_file:
892  // We can't process DW_LNE_define_file here, as it would require us to
893  // use unbounded amounts of state (ie. use the heap). We'll do a second
894  // pass (using nextDefineFile()) if necessary.
895  break;
896  case DW_LNE_set_discriminator:
897  discriminator_ = readULEB(program);
898  return CONTINUE;
899  }
900 
901  // Unrecognized extended opcode
902  program.advance(length);
903  return CONTINUE;
904 }
void advance(size_type n)
Definition: Range.h:672
const uint8_t * standardOpcodeLengths_
Definition: Dwarf.h:242
#define FOLLY_SAFE_CHECK(expr, msg)
Definition: SafeAssert.h:35

Member Data Documentation

uint64_t folly::symbolizer::Dwarf::LineNumberVM::address_
private

Definition at line 251 of file Dwarf.h.

Referenced by findAddress(), reset(), and step().

bool folly::symbolizer::Dwarf::LineNumberVM::basicBlock_
private

Definition at line 256 of file Dwarf.h.

Referenced by reset(), and step().

uint64_t folly::symbolizer::Dwarf::LineNumberVM::column_
private

Definition at line 254 of file Dwarf.h.

Referenced by reset(), and step().

folly::StringPiece folly::symbolizer::Dwarf::LineNumberVM::compilationDirectory_
private

Definition at line 233 of file Dwarf.h.

Referenced by findAddress().

folly::StringPiece folly::symbolizer::Dwarf::LineNumberVM::data_
private

Definition at line 232 of file Dwarf.h.

Referenced by findAddress(), getFileName(), init(), and LineNumberVM().

bool folly::symbolizer::Dwarf::LineNumberVM::defaultIsStmt_
private

Definition at line 238 of file Dwarf.h.

Referenced by init(), and reset().

uint64_t folly::symbolizer::Dwarf::LineNumberVM::discriminator_
private

Definition at line 261 of file Dwarf.h.

Referenced by reset(), and step().

bool folly::symbolizer::Dwarf::LineNumberVM::endSequence_
private

Definition at line 257 of file Dwarf.h.

Referenced by reset().

bool folly::symbolizer::Dwarf::LineNumberVM::epilogueBegin_
private

Definition at line 259 of file Dwarf.h.

Referenced by reset(), and step().

uint64_t folly::symbolizer::Dwarf::LineNumberVM::file_
private

Definition at line 252 of file Dwarf.h.

Referenced by findAddress(), reset(), and step().

size_t folly::symbolizer::Dwarf::LineNumberVM::fileNameCount_
private

Definition at line 248 of file Dwarf.h.

Referenced by getFileName(), and init().

folly::StringPiece folly::symbolizer::Dwarf::LineNumberVM::fileNames_
private

Definition at line 247 of file Dwarf.h.

Referenced by getFileName(), and init().

folly::StringPiece folly::symbolizer::Dwarf::LineNumberVM::includeDirectories_
private

Definition at line 244 of file Dwarf.h.

Referenced by getIncludeDirectory(), and init().

size_t folly::symbolizer::Dwarf::LineNumberVM::includeDirectoryCount_
private

Definition at line 245 of file Dwarf.h.

Referenced by getIncludeDirectory(), and init().

bool folly::symbolizer::Dwarf::LineNumberVM::is64Bit_
private

Definition at line 231 of file Dwarf.h.

Referenced by init(), and LineNumberVM().

uint64_t folly::symbolizer::Dwarf::LineNumberVM::isa_
private

Definition at line 260 of file Dwarf.h.

Referenced by reset(), and step().

bool folly::symbolizer::Dwarf::LineNumberVM::isStmt_
private

Definition at line 255 of file Dwarf.h.

Referenced by reset(), and step().

uint64_t folly::symbolizer::Dwarf::LineNumberVM::line_
private

Definition at line 253 of file Dwarf.h.

Referenced by findAddress(), reset(), and step().

int8_t folly::symbolizer::Dwarf::LineNumberVM::lineBase_
private

Definition at line 239 of file Dwarf.h.

Referenced by init(), and step().

uint8_t folly::symbolizer::Dwarf::LineNumberVM::lineRange_
private

Definition at line 240 of file Dwarf.h.

Referenced by init(), and step().

uint8_t folly::symbolizer::Dwarf::LineNumberVM::minLength_
private

Definition at line 237 of file Dwarf.h.

Referenced by init(), and step().

uint8_t folly::symbolizer::Dwarf::LineNumberVM::opcodeBase_
private

Definition at line 241 of file Dwarf.h.

Referenced by init(), nextDefineFile(), and step().

bool folly::symbolizer::Dwarf::LineNumberVM::prologueEnd_
private

Definition at line 258 of file Dwarf.h.

Referenced by reset(), and step().

const uint8_t* folly::symbolizer::Dwarf::LineNumberVM::standardOpcodeLengths_
private

Definition at line 242 of file Dwarf.h.

Referenced by init(), nextDefineFile(), and step().

uint16_t folly::symbolizer::Dwarf::LineNumberVM::version_
private

Definition at line 236 of file Dwarf.h.

Referenced by init(), and step().


The documentation for this class was generated from the following files: