Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Platform(oh::ObjectHandle) #41

Merged
merged 1 commit into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Abstract/ObjectHandle.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ where `oh <: COFFHandle`).
- unpack()

### Format-specific properties
- *Platform()*
- *endianness()*
- *is64bit()*
- *isrelocatable()*
Expand Down Expand Up @@ -189,6 +190,12 @@ for f in [:skip, :seekstart, :eof, :read, :readuntil, :readbytes, :write]
@eval $(f)(oh::H, args...) where {H<:ObjectHandle} = $(f)(iostream(oh), args...)
end

"""
Platform(oh::ObjectHandle)

Returns a `Platform` object representing the binary platform this object is built for.
"""
@mustimplement Platform(oh::ObjectHandle)

"""
endianness(oh::ObjectHandle)
Expand Down
3 changes: 2 additions & 1 deletion src/COFF/COFF.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module COFF

using StructIO
using StructIO, Base.BinaryPlatforms
import Base.BinaryPlatforms: Platform

# Bring in ObjectFile definitions
using ObjectFile
Expand Down
1 change: 1 addition & 0 deletions src/COFF/COFFHandle.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ iostream(oh::COFFHandle) = oh.io

## Format-specific properties:
header(oh::COFFHandle) = oh.header
Platform(oh::COFFHandle) = Platform(coff_machine_to_arch(oh.header.Machine), "windows")
endianness(oh::COFFHandle) = coff_header_endianness(header(oh))
is64bit(oh::COFFHandle) = coff_header_is64bit(header(oh))
isrelocatable(oh::COFFHandle) = isrelocatable(header(oh))
Expand Down
14 changes: 14 additions & 0 deletions src/COFF/constants.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@
const IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169 # MIPS little-endian WCE v2
end

function coff_machine_to_arch(machine::UInt16)
if machine ∈ (IMAGE_FILE_MACHINE_I386,)
return "i686"
elseif machine ∈ (IMAGE_FILE_MACHINE_AMD64, IMAGE_FILE_MACHINE_IA64)
return "x86_64"
elseif machine ∈ (IMAGE_FILE_MACHINE_ARM, IMAGE_FILE_MACHINE_ARMNT, IMAGE_FILE_MACHINE_THUMB)
return "armv7l"
elseif machine ∈ (IMAGE_FILE_MACHINE_ARM64,)
return "aarch64"
elseif machine ∈ (IMAGE_FILE_MACHINE_POWERPC,)
return "ppc64le"
end
end

# # # Characteristics

@constants IMAGE_FILE_CHARACTERISTICS "IMAGE_FILE_" begin
Expand Down
3 changes: 2 additions & 1 deletion src/ELF/ELF.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module ELF

using StructIO
using StructIO, Base.BinaryPlatforms
import Base.BinaryPlatforms: Platform

# Bring in ObjectFile definitions
using ObjectFile
Expand Down
6 changes: 6 additions & 0 deletions src/ELF/ELFHandle.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,15 @@ end
startaddr(oh::ELFHandle) = oh.start
iostream(oh::ELFHandle) = oh.io

# We don't try to inspect dynamic libraries to figure out if this is a glibc or musl dynamic object
function strip_libc_tag(p::Platform)
delete!(tags(p), "libc")
return p
end

## Format-specific properties:
header(oh::ELFHandle) = oh.header
Platform(oh::ELFHandle) = strip_libc_tag(Platform(elf_machine_to_arch(oh.header.e_machine), "linux"))
endianness(oh::ELFHandle) = elf_internal_endianness(oh.ei)
is64bit(oh::ELFHandle) = elf_internal_is64bit(oh.ei)
isrelocatable(oh::ELFHandle) = header(oh).e_type == ET_REL
Expand Down
14 changes: 14 additions & 0 deletions src/ELF/ELFHeader.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,20 @@ function machinetype(e_machine)
return string("Unknown (0x",string(e_machine, base=16),")")
end

function elf_machine_to_arch(machine::UInt16)
if machine ∈ (EM_386,)
return "i686"
elseif machine ∈ (EM_IA_64, EM_X86_64)
return "x86_64"
elseif machine ∈ (EM_ARM,)
return "armv7l"
elseif machine ∈ (EM_AARCH64,)
return "aarch64"
elseif machine ∈ (EM_PPC64,)
return "ppc64le"
end
end


function show(io::IO, header::ELFHeader)
println(io, "ELF Header")
Expand Down
3 changes: 2 additions & 1 deletion src/MachO/MachO.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module MachO

using StructIO
using StructIO, Base.BinaryPlatforms
import Base.BinaryPlatforms: Platform

# Bring in ObjectFile definitions
using ObjectFile
Expand Down
1 change: 1 addition & 0 deletions src/MachO/MachOHandle.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ iostream(oh::AbstractMachOHandle) = oh.io
## Format-specific properties:
header(oh::AbstractMachOHandle) = oh.header
endianness(oh::AbstractMachOHandle) = macho_endianness(header(oh).magic)
Platform(oh::MachOHandle) = Platform(macho_cpu_to_arch(header(oh).cputype), "macos")
is64bit(oh::MachOHandle) = macho_is64bit(header(oh).magic)
isrelocatable(oh::MachOHandle) = header(oh).filetype == MH_OBJECT
isexecutable(oh::MachOHandle) = header(oh).filetype == MH_EXECUTE
Expand Down
15 changes: 15 additions & 0 deletions src/MachO/constants.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,21 @@ const CPU_ARCH_ABI64_32 = 0x02000000
const CPU_TYPE_ARM64_32 = CPU_TYPE_ARM | CPU_ARCH_ABI64_32
end

function macho_cpu_to_arch(cputype::UInt32)
if cputype ∈ (CPU_TYPE_X86,)
return "i686"
elseif cputype ∈ (CPU_TYPE_X86_64,)
return "x86_64"
elseif cputype ∈ (CPU_TYPE_ARM,)
return "armv7l"
elseif cputype ∈ (CPU_TYPE_POWERPC64,)
return "ppc64le"
elseif cputype ∈ (CPU_TYPE_ARM64,)
return "aarch64"
end
end


# TODO subtype constants
@constants NLISTTYPES "N_" begin
const N_STAB = 0xe0
Expand Down
1 change: 1 addition & 0 deletions src/ObjectFile.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module ObjectFile
using Reexport
import Base.BinaryPlatforms: Platform

# Include base utilities
include("utils.jl")
Expand Down
11 changes: 10 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using ObjectFile
using ObjectFile, Base.BinaryPlatforms
using Test

@testset "basic" begin
Expand Down Expand Up @@ -29,6 +29,14 @@ function test_libfoo_and_fooifier(fooifier_path, libfoo_path)
H = types[platform]
bits = dir_path[end-1:end]

platforms = Dict(
"linux32" => Platform("i686", "linux"),
"linux64" => Platform("x86_64", "linux"),
"mac64" => Platform("x86_64", "macos"),
"win32" => Platform("i686", "windows"),
"win64" => Platform("x86_64", "windows"),
)

@testset "$(dir_path)" begin
@testset "General Properties" begin
for oh in (oh_exe, oh_lib)
Expand All @@ -37,6 +45,7 @@ function test_libfoo_and_fooifier(fooifier_path, libfoo_path)

# Test that we got the right number of bits
@test is64bit(oh) == (bits == "64")
@test platforms_match(Platform(oh), platforms[dir_path])

# Everything is always little endian
@test endianness(oh) == :LittleEndian
Expand Down