⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dwarfutils.pas

📁 一个不出名的GBA模拟器
💻 PAS
📖 第 1 页 / 共 4 页
字号:

  TDwarfSubroutine = class
    name: string;
    node: PDwarfNode;
    lowPC, highPC: uint32;
    fileIndex, line, column: integer;
  end;

  TDwarfVariable = class
    name: string;
    node: PDwarfNode;
    fileIndex, line, column: integer;
    startScope: uint32;
    loc: PDwarfAttribute;
    typ: PDwarfAttribute;
  end;

  TDwarfType = class
    name: string;
    node: PDwarfNode;
    fileIndex, line, column: integer;


    isBasic: boolean;    // Whether or not its a basic type (if true, encoding is valid)
    encoding: integer;   // DW_ATE_*
    size: integer;       // size (in bytes)
    bitSize, bitOffset: integer; // for sub-byte variables (I'll probably ignore it)
  end;

//////////////////////////////////////////////////////////////////////

var
  dwarf: TDwarfFile;

function ProcessDWARF(elf: TELFFile; dir: string): TDwarfFile;
procedure ProcessNode(cunit: TCompilationUnit; node: PDwarfNode);
function DoLineProgram(building: boolean; cunit: TCompilationUnit; target: uint32; var hit: TLineHit): boolean;
function FindLineInP(target: uint32; var hit: TLineHit): boolean;
procedure WalkVariables(var res: TStringList);
function ExamineVariable(name: string): integer;
function LocationSM(block: TDwarfBlock; var inRegister, notOptimized: boolean): uint32;
function FindAttribute(node: PDwarfNode; name: uint32): PDwarfAttribute;

//////////////////////////////////////////////////////////////////////
implementation ///////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

uses
  observerCSource;

//////////////////////////////////////////////////////////////////////

const
  tagStrings: array[0..DW_TAG_volatile_type] of string = (
    'DW_TAG_null',
    'DW_TAG_array_type',
    'DW_TAG_class_type',
    'DW_TAG_entry_point',
    'DW_TAG_enumeration_type',
    'DW_TAG_formal_parameter',
    '',
    '',
    'DW_TAG_imported_declaration',
    '',
    'DW_TAG_label',
    'DW_TAG_lexical_block',
    '',
    'DW_TAG_member',
    '',
    'DW_TAG_pointer_type',
    'DW_TAG_reference_type',
    'DW_TAG_compile_unit',
    'DW_TAG_string_type',
    'DW_TAG_structure_type',
    '',
    'DW_TAG_subroutine_type',
    'DW_TAG_typedef',
    'DW_TAG_union_type',
    'DW_TAG_unspecified_parameters',
    'DW_TAG_variant',
    'DW_TAG_common_block',
    'DW_TAG_common_inclusion',
    'DW_TAG_inheritance',
    'DW_TAG_inlined_subroutine',
    'DW_TAG_module',
    'DW_TAG_ptr_to_member_type',
    'DW_TAG_set_type',
    'DW_TAG_subrange_type',
    'DW_TAG_with_stmt',
    'DW_TAG_access_declaration',
    'DW_TAG_base_type',
    'DW_TAG_catch_block',
    'DW_TAG_const_type',
    'DW_TAG_constant',
    'DW_TAG_enumerator',
    'DW_TAG_file_type',
    'DW_TAG_friend',
    'DW_TAG_namelist',
    'DW_TAG_namelist_item',
    'DW_TAG_packed_type',
    'DW_TAG_subprogram',
    'DW_TAG_template_type_param',
    'DW_TAG_template_value_param',
    'DW_TAG_thrown_type',
    'DW_TAG_try_block',
    'DW_TAG_variant_part',
    'DW_TAG_variable',
    'DW_TAG_volatile_type'
    );

  attribStrings: array[0..DW_AT_vtable_elem_location] of string = (
    '',
    'DW_AT_sibling',
    'DW_AT_location',
    'DW_AT_name',
    '',
    '',
    '',
    '',
    '',
    'DW_AT_ordering',
    '',
    'DW_AT_byte_size',
    'DW_AT_bit_offset',
    'DW_AT_bit_size',
    '',
    '',
    'DW_AT_stmt_list',
    'DW_AT_low_pc',
    'DW_AT_high_pc',
    'DW_AT_language',
    '',
    'DW_AT_discr',
    'DW_AT_discr_value',
    'DW_AT_visibility',
    'DW_AT_import',
    'DW_AT_string_length',
    'DW_AT_common_reference',
    'DW_AT_comp_dir',
    'DW_AT_const_value',
    'DW_AT_containing_type',
    'DW_AT_default_value',
    '',
    'DW_AT_inline',
    'DW_AT_is_optional',
    'DW_AT_lower_bound',
    '',
    '',
    'DW_AT_producer',
    '',
    'DW_AT_prototyped',
    '',
    '',
    'DW_AT_return_addr',
    '',
    'DW_AT_start_scope',
    '',
    'DW_AT_stride_size',
    'DW_AT_upper_bound',
    '',
    'DW_AT_abstract_origin',
    'DW_AT_accessibility',
    'DW_AT_address_class',
    'DW_AT_artificial',
    'DW_AT_base_types',
    'DW_AT_calling_convention',
    'DW_AT_count',
    'DW_AT_data_member_location',
    'DW_AT_decl_column',
    'DW_AT_decl_file',
    'DW_AT_decl_line',
    'DW_AT_declaration',
    'DW_AT_discr_list',
    'DW_AT_encoding',
    'DW_AT_external',
    'DW_AT_frame_base',
    'DW_AT_friend',
    'DW_AT_identifier_case',
    'DW_AT_macro_info',
    'DW_AT_namelist_item',
    'DW_AT_priority',
    'DW_AT_segment',
    'DW_AT_specification',
    'DW_AT_static_link',
    'DW_AT_type',
    'DW_AT_use_location',
    'DW_AT_variable_parameter',
    'DW_AT_virtuality',
    'DW_AT_vtable_elem_location'
  );

  formStrings: array[0..DW_FORM_indirect] of string = (
    'Unknown form 0',
    'DW_FORM_addr',
    'Unknown form 2',
    'DW_FORM_block2',
    'DW_FORM_block4',
    'DW_FORM_data2',
    'DW_FORM_data4',
    'DW_FORM_data8',
    'DW_FORM_string',
    'DW_FORM_block',
    'DW_FORM_block1',
    'DW_FORM_data1',
    'DW_FORM_flag',
    'DW_FORM_sdata',
    'DW_FORM_strp',
    'DW_FORM_udata',
    'DW_FORM_ref_addr',
    'DW_FORM_ref1',
    'DW_FORM_ref2',
    'DW_FORM_ref4',
    'DW_FORM_ref8',
    'DW_FORM_ref_udata',
    'DW_FORM_indirect');

  langStrings: array[0..DW_LANG_Modula2] of string = (
    '',
    'DW_LANG_C89',
    'DW_LANG_C',
    'DW_LANG_Ada83',
    'DW_LANG_C_plus_plus',
    'DW_LANG_Cobol74',
    'DW_LANG_Cobol85',
    'DW_LANG_Fortran77',
    'DW_LANG_Fortran90',
    'DW_LANG_Pascal83',
    'DW_LANG_Modula2');

//////////////////////////////////////////////////////////////////////

function DwarfFormToString(form: uint32): string;
begin
  if form <= DW_FORM_indirect then
    Result := formStrings[form]
  else
    Result := Format('<unk. form $%x>', [form]);
end;

//////////////////////////////////////////////////////////////////////

function DwarfAttributeToString(attrib: uint32): string;
begin
  if attrib <= DW_AT_vtable_elem_location then
    Result := attribStrings[attrib]
  else begin
    if attrib = $2000 then
      Result := 'DW_AT_proc_body'
    else if attrib = $2001 then
      Result := 'DW_AT_save_offset'
    else if attrib = $2002 then
      Result := 'DW_AT_codeseg_base'
    else if attrib = $2007 then
      Result := 'DW_AT_MIPS_linkage_name'
    else
      Result := Format('<unk. attribute $%x>', [attrib]);
  end;
end;

//////////////////////////////////////////////////////////////////////

function DwarfTagToString(tag: uint32): string;
begin
  if tag <= DW_TAG_volatile_type then
    Result := tagStrings[tag]
  else
    Result := Format('<unk. tag $%x>', [tag]);
end;

//////////////////////////////////////////////////////////////////////

function DwarfLangToString(lang: uint32): string;
begin
  if lang <= DW_LANG_Modula2 then
    Result := langStrings[lang]
  else
    Result := Format('<unk. lang $%x>', [lang]);
end;

//////////////////////////////////////////////////////////////////////

var
  debugAbbrev, debugAranges, debugFrame, debugInfo, debugLine,
  debugLoc, debugMacInfo, debugPubNames, debugStr: TElfSection;

//////////////////////////////////////////////////////////////////////

function ReadTSRegister(index: integer): integer;
begin
  Result := vmGetRegister(index);
end;

//////////////////////////////////////////////////////////////////////

function ReadTSAddress(addr: uint32): uint32;
begin
  Result := vmReadWord(addr);
end;

//////////////////////////////////////////////////////////////////////

function ReadTSUint8(addr: uint32): uint32;
begin
  Result := vmReadByte(addr);
end;

//////////////////////////////////////////////////////////////////////

procedure ReadAttribute(attrib: PDwarfAttribute);
var
  temp: uint32;
begin
  with debugInfo do begin
    case attrib^.format of
      DW_FORM_addr: attrib^.address := ReadAddress;
      DW_FORM_block2: begin
        attrib^.block.size := ReadUint16;
        attrib^.block.data := dataPointer;
        SeekRelAddress(attrib^.block.size);
      end;
      DW_FORM_block4: begin
        attrib^.block.size := ReadUint32;
        attrib^.block.data := dataPointer;
        SeekRelAddress(attrib^.block.size);
      end;
      DW_FORM_data2: attrib^.data := ReadUint16;
      DW_FORM_data4: attrib^.data := ReadUint32;
      DW_FORM_data8: attrib^.data := ReadUint64;
      DW_FORM_string: attrib^.st := ReadString;
      DW_FORM_block: begin
        attrib^.block.size := ReadLEB128;
        attrib^.block.data := dataPointer;
        SeekRelAddress(attrib^.block.size);
      end;
      DW_FORM_block1: begin
        attrib^.block.size := ReadUint8;
        attrib^.block.data := dataPointer;
        SeekRelAddress(attrib^.block.size);
      end;
      DW_FORM_data1: attrib^.data := ReadUint8;
      DW_FORM_flag: attrib^.flag := ReadUint8 <> 0;
      DW_FORM_sdata: attrib^.data := ReadSLEB128;
      DW_FORM_strp: begin
        temp := ReadUint32;
        if debugStr <> nil then
          attrib^.st := pointer(uint32(debugStr.data) + temp);// todo: should be a readstring?
      end;
      DW_FORM_udata: attrib^.data := ReadLEB128;
      DW_FORM_ref_addr: attrib^.offset := ReadAddress;
      DW_FORM_ref1: attrib^.offset := ReadUint8;
      DW_FORM_ref2: attrib^.offset := ReadUint16;
      DW_FORM_ref4: attrib^.offset := ReadUint32;
      DW_FORM_ref8: attrib^.offset := ReadUint64;
      DW_FORM_ref_udata: attrib^.offset := ReadLEB128;
      DW_FORM_indirect: begin
        attrib^.format := ReadLEB128;
        if attrib^.format <> DW_FORM_indirect then
          ReadAttribute(attrib)
        else
          logWriteLn('dwarfUtils.ReadAttribute: Error, DW_FORM_indirect loop');
      end;
    else
      logWriteLn('dwarfUtils.ReadAttribute: Error, unknown form ' + IntToStr(attrib^.format));
    end;
  end;
end;

//////////////////////////////////////////////////////////////////////

// returns true if found, false otherwise
function FindAbbreviation(cunit: TCompilationUnit; abbreviation: uint32): boolean;
var
  code, a, b: uint32;
begin
  debugAbbrev.Seek(cunit.abbrevOffset);
  repeat
    // Read the abbreviation code (abbrev = 0 denotes the end entry)
    code := debugAbbrev.ReadLEB128;
    if code = abbreviation then begin
      Result := true;
      Exit;
    end;

    // Eat the tag and children flag
    debugAbbrev.ReadLEB128;
    debugAbbrev.ReadUint8;

    // Skip over the attributes
    repeat
      a := debugAbbrev.ReadLEB128;
      b := debugAbbrev.ReadLEB128;
    until (a = 0) and (b = 0);
  until code = 0;
  Result := false;
end;

//////////////////////////////////////////////////////////////////////

function ReadNode(cunit: TCompilationUnit): PDwarfNode;
var
  lastAttrib: ^PDwarfAttribute;
  attrib: PDwarfAttribute;
  abbrev: uint32;
  lnode, node: PDwarfNode;
  name, format: uint32;
begin
  Result := nil;
  node := nil;

  // Read the abbreviation from the .debug_info section
  repeat
    // Check the abbreviation code (0 is a reserved code)
    abbrev := debugInfo.ReadLEB128;
    if abbrev = 0 then Break;

    // Create a new sibling node
    lnode := node;
    GetMem(node, SizeOf(TDwarfNode));
    if Assigned(lnode) then lnode^.next := node else Result := node;

    // Initialize the new node
    node^.abbreviation := abbrev;
    node^.next := nil;
    node^.attribs := nil;
    node^.kids := nil;
    node^.tag := DW_TAG_friend;

    // Read the attribute names and formats from the .debug_abbrev section
    if FindAbbreviation(cunit, node^.abbreviation) then begin
      node^.tag := debugAbbrev.ReadLEB128;
      node^.hasChildren := debugAbbrev.ReadUint8 = DW_CHILDREN_yes;

      lastAttrib := @(node^.attribs);
      repeat
        name := debugAbbrev.ReadLEB128;
        format := debugAbbrev.ReadLEB128;

        if (name = 0) and (format = 0) then begin
          lastAttrib^ := nil;
          Break;
        end else begin
          // Create a new attribute
          GetMem(attrib, SizeOf(TDwarfAttribute));
          attrib^.name := name;
          attrib^.format := format;
          attrib^.next := nil;
          ReadAttribute(attrib);
          lastAttrib^ := attrib;
          lastAttrib := @(attrib^.next);
        end;
      until false;

      // Read the attribute data from the .debug_info section
{      attrib := node^.attribs;
      while attrib <> nil do begin
        ReadAttribute(attrib);
        attrib := attrib^.next;
      end;}

      // Recursively get all the children
      if node^.hasChildren then node^.kids := ReadNode(cunit);
    end else
      logWriteLn('dwarfUtils.ReadNode: Error, abbreviation ' + IntToStr(node^.abbreviation) + ' not found in .debug_abbrev contribution for current compilation unit');
  until false;
end;

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

function LocationSM(block: TDwarfBlock; var inRegister, notOptimized: boolean): uint32;
var
  stackIndex: integer;
  stack: array[0..63] of uint32;

procedure Push(addr: uint32);
begin
  stackIndex := (stackIndex-1) and 63;
  stack[stackIndex] := addr;
end;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -