lazarus/components/fpdebug/fpimgreadermachofile.pas

138 lines
3.2 KiB
ObjectPascal

unit FpImgReaderMachoFile;
{$T-} // TODO: Fix compilation with -Sy.
{$mode objfpc}{$H+}
interface
//todo: powerpc, x86_64
uses
Classes, SysUtils, macho, FpImgReaderBase,
FpDbgCommon;
type
TMachOsection = class(TObject)
is32 : Boolean;
sec32 : section;
sec64 : section_64;
end;
{ TMachOFile }
TMachOFile = class(TObject)
private
cmdbuf : array of byte;
FTargetInfo : TTargetDescriptor;
public
header : mach_header;
commands : array of pload_command;
sections : TFPList;
UUID : TGuid;
constructor Create;
destructor Destroy; override;
function LoadFromFile(ALoader: TDbgFileLoader): Boolean;
property TargetInfo: TTargetDescriptor read FTargetInfo;
end;
implementation
{ TMachOFile }
constructor TMachOFile.Create;
begin
sections := TFPList.Create;
end;
destructor TMachOFile.Destroy;
var
i : integer;
begin
for i := 0 to sections.Count - 1 do TMachOsection(sections[i]).Free;
sections.Free;
inherited Destroy;
end;
function TMachOFile.LoadFromFile(ALoader: TDbgFileLoader): Boolean;
var
i : Integer;
j : Integer;
ofs : Integer;
sc32: psection;
sc64: psection_64;
idcm: puuid_command;
s : TMachOsection;
hs : integer;
i64 : boolean;
begin
Result := ALoader.Read(0, sizeof(header), @header) = sizeof(header);
if not Result then Exit;
i64 := (header.magic = MH_CIGAM_64) or (header.magic = MH_MAGIC_64);
Result := (header.magic = MH_MAGIC) or (header.magic = MH_CIGAM) or i64;
if i64 then
begin
hs := sizeof(mach_header_64);
FTargetInfo.bitness := b64;
end
else
begin
hs := SizeOf(mach_header);
FTargetInfo.bitness := b32;
end;
case header.cputype of
CPU_TYPE_I386 : FTargetInfo.MachineType := mt386;
CPU_TYPE_ARM : FTargetInfo.MachineType := mtARM;
CPU_TYPE_SPARC : FTargetInfo.MachineType := mtSPARC;
//CPU_TYPE_ALPHA : FTargetInfo.MachineType := mtALPHA;
CPU_TYPE_POWERPC : FTargetInfo.MachineType := mtPPC;
CPU_TYPE_POWERPC64 : FTargetInfo.MachineType := mtPPC;
CPU_TYPE_X86_64 : FTargetInfo.MachineType := mtX86_64;
CPU_TYPE_ARM64 : FTargetInfo.MachineType := mtARM;
else
FTargetInfo.machineType := mtNone;
end;
SetLength(cmdbuf, header.sizeofcmds);
ALoader.Read(hs, header.sizeofcmds, @cmdbuf[0]);
SetLength(commands, header.ncmds);
ofs := 0;
for i := 0 to header.ncmds - 1 do begin
commands[i] := @cmdbuf[ofs];
if commands[i]^.cmd = LC_SEGMENT then begin
sc32 := @cmdbuf[ofs+sizeof(segment_command)];
for j := 0 to psegment_command(commands[i])^.nsects- 1 do begin
s := TMachOSection.Create;
s.is32:=true;
s.sec32:=sc32^;
sections.add(s);
inc(sc32);
end;
end
else if commands[i]^.cmd = LC_SEGMENT_64 then begin
sc64 := @cmdbuf[ofs+sizeof(segment_command_64)];
for j := 0 to psegment_command_64(commands[i])^.nsects- 1 do begin
s := TMachOSection.Create;
s.is32:=False;
s.sec64:=sc64^;
sections.add(s);
inc(sc64);
end;
end
else if commands[i]^.cmd = LC_UUID then begin
idcm := @cmdbuf[ofs];
UUID:=PGuid(@(idcm^.uuid))^;
end;
inc(ofs, commands[i]^.cmdsize);
end;
end;
end.