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

📄 elfutils.pas

📁 一个不出名的GBA模拟器
💻 PAS
📖 第 1 页 / 共 2 页
字号:
function TELFSection.Name: string;
begin
  Result := FParent.ReadString(FHeader^.sh_name);
end;

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

procedure TELFSection.ProcessSymtab(q: integer);
{const
  types: array[0..15] of string = ('N/A', 'Object', 'Function',
  'Section', 'File', '','','','','','','','','Lo Proc','','Hi Proc');
type
  TSymbolTable = array[0..0] of TElf32SymbolEntry;
  PSymbolTable = ^TSymbolTable;
var
  section: TElfSection;
  sym: PSymbolTable;
  i: integer;}
begin
{  section := FParent.Sections[FHeader^.sh_link];
  sym := @(data^);
  if FHeader^.sh_type = SECTION_TYPE_SYMTAB then
    for i := 0 to (FHeader^.sh_size div FHeader^.sh_entsize) - 1 do if sym^[i].sectionIndex < SECTION_LORESERVE then begin
        printf(Format('%-33s is at $%8.8x, of type %-8s and size %-4d]', [section.ReadString(sym^[i].st_name), sym^[i].st_value, types[sym^[i].st_info and $F], sym^[i].st_size]));
    end;}
end;

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

function TELFSection.ReadElfString(index: integer): string;
begin
  if (index < $FF00) and (FHeader^.sh_type = SECTION_TYPE_STRTAB) then
    Result := PChar(@(data^[index]))
  else
    Result := '';
end;

//////////////////////////////////////////////////////////////////////
// TReadableResource /////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

function TReadableResource.ReadUint8: uint32;
begin
  Result := Puint8(dataPointer)^;
  dataPointer := pointer(integer(dataPointer) + 1);
end;

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

function TReadableResource.ReadInt8: int32;
begin
  Result := Pint8(dataPointer)^;
  dataPointer := pointer(integer(dataPointer) + 1);
end;

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

function TReadableResource.ReadUint16: uint32;
begin
  Result := Puint16(dataPointer)^;
  dataPointer := pointer(integer(dataPointer) + 2);
end;

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

function TReadableResource.ReadInt16: int32;
begin
  Result := Pint16(dataPointer)^;
  dataPointer := pointer(integer(dataPointer) + 2);
end;

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

function TReadableResource.ReadUint32: uint32;
begin
  Result := Puint32(dataPointer)^;
  dataPointer := pointer(integer(dataPointer) + 4);
end;

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

function TReadableResource.ReadInt32: int32;
begin
  Result := Pint32(dataPointer)^;
  dataPointer := pointer(integer(dataPointer) + 4);
end;

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

function TReadableResource.ReadUint64: uint32;
begin
  // fixme!
  ReadUint32;
  Result := ReadUint32;
end;

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

function TReadableResource.ReadInt64: int32;
begin
  ReadInt32;
  Result := ReadInt32;
end;

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

function TReadableResource.ReadLEB128: uint32;
var
  shift: integer;
  b: byte;
begin
  Result := 0;
  shift := 0;
  repeat
    b := ReadUint8;
    Result := Result or ((b and $7F) shl shift);
    shift := shift + 7;
  until b and (1 shl 7) = 0;
end;

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

function TReadableResource.ReadSLEB128: int32;
var
  shift: integer;
  b: byte;
begin
  Result := 0;
  shift := 0;
  repeat
    b := ReadUint8;
    Result := Result or ((b and $7F) shl shift);
    shift := shift + 7;
  until b and (1 shl 7) = 0;

  if (shift < 32) and (b and (1 shl 6) <> 0) then
    Result := Result or (-(1 shl shift));
end;

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

procedure TReadableResource.ReadBlock(var block; size: uint32);
begin
  Move((dataPointer)^, block, size);
  dataPointer := pointer(uint32(dataPointer) + size);
end;

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

function TReadableResource.ReadString: PChar;
begin
  Result := dataPointer;
  dataPointer := pointer(integer(dataPointer) + Length(Result) + 1);
end;

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

function TReadableResource.ReadAddress: uint32;
begin
  Result := ReadUint32;
end;

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

procedure TReadableResource.SeekRelAddress(offset: integer);
begin
  dataPointer := pointer(integer(dataPointer) + offset);
end;

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

procedure TReadableResource.Seek(absOffset: integer);
begin
  dataPointer := pointer(integer(data) + absOffset);
end;

//////////////////////////////////////////////////////////////////////
// TElfFile //////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

procedure TELFFile.Build;
var
  i: uint32;
  section: TElfSection;
begin
  // Load the sections into their own classes
  FSections := TObjectList.Create;
  for i := 0 to header^.numSectionEntries - 1 do begin
    section := TElfSection.Create(self, @(data^[header^.sectionTableOffset + i * SizeOf(TElf32SectionHeader)]));
    FSections.Add(section);
  end;
end;

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

constructor TELFFile.Create(stream: TStream);
begin
  // Read in the data from the stream
  size := stream.Size;
  GetMem(data, size);
  stream.Read(data^, size);

  // Access the header
  header := PElf32Header(data);

  // Verify its a valid version 1 little-endian executable 32-bit ARM ELF file
  if (header.ident[ELF_INDEX_MAGIC0] = ELF_MAGIC0) and
     (header.ident[ELF_INDEX_MAGIC1] = ELF_MAGIC1) and
     (header.ident[ELF_INDEX_MAGIC2] = ELF_MAGIC2) and
     (header.ident[ELF_INDEX_MAGIC3] = ELF_MAGIC3) and
     (header.ident[ELF_INDEX_CLASS] = ELF_CLASS_32) and
     (header.ident[ELF_INDEX_DATA] = ELF_DATA_LSB) and
     (header.ident[ELF_INDEX_VERSION] = ELF_VERSION_CURRENT) and
     (header.elfType = ELF_TYPE_EXEC) and
     (header.machine = ELF_MACHINE_ARM) and
     (header.version = ELF_VERSION_CURRENT) then else Free;
end;

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

destructor TELFFile.Destroy;
begin
  FreeMem(data, size);
  FSections.Free;
  inherited;
end;

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

function TELFFile.FindSectionByName(name: string): TElfSection;
var
  index: integer;
begin
  for index := 0 to NumSections - 1 do begin
    Result := Sections[index];
    if Result.name = name then Exit;
  end;
  Result := nil;
end;

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

function RoundUpToPow2(num: uint32): uint32;
begin
  Result := 1;
  while Result < num do Result := Result shl 1;
end;

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

// Flattens any run-time active segments into a linear image, stored
// in data, and returns the size of this image
function TELFFile.Flatten(var data: Puint8array): integer;
var
  acc, size: longword;
  i: integer;
  section: TElfSection;
begin
  size := 0;
  for i := 0 to NumSections - 1 do begin
    section := Sections[i];
    if section.HasSubstance then Inc(size, section.FHeader.sh_size);
  end;

  // Spew the segments into a memory buffer
  Result := RoundUpToPow2(size);
  GetMem(data, Result);
  acc := 0;
  for i := 0 to NumSections - 1 do begin
    section := Sections[i];
    if section.HasSubstance then begin
      Move(section.data^, data^[acc], section.FHeader.sh_size);
      acc := acc + section.FHeader.sh_size;
    end;
  end;
end;

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

function TELFFile.GetSection(index: integer): TElfSection;
begin
  Result := TElfSection(FSections.Items[index]);
end;

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

function TELFFile.NumSections: integer;
begin
  Result := FSections.Count;
end;

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

function TELFFile.ReadString(index: integer): string;
begin
  if (header^.stringTableIndex > 0) and (header^.stringTableIndex < SECTION_LORESERVE) then
    Result := Sections[header^.stringTableIndex].ReadElfString(index)
  else
    Result := '';
end;

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

end.

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

⌨️ 快捷键说明

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