summaryrefslogtreecommitdiff
path: root/xmake/core/base/binutils.lua
blob: b513be0b109bd7118b9bb30344301529da27c251 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
--!A cross-platform build utility based on Lua
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-- Copyright (C) 2015-present, Xmake Open Source Community.
--
-- @author      ruki
-- @file        binutils.lua
--

-- define module
local binutils = binutils or {}

-- load modules
local os = require("base/os")

-- save original interfaces
binutils._bin2c = binutils._bin2c or binutils.bin2c
binutils._bin2coff = binutils._bin2coff or binutils.bin2coff
binutils._bin2macho = binutils._bin2macho or binutils.bin2macho
binutils._bin2elf = binutils._bin2elf or binutils.bin2elf
binutils._readsyms = binutils._readsyms or binutils.readsyms
binutils._deplibs = binutils._deplibs or binutils.deplibs
binutils._rpath_list = binutils._rpath_list or binutils.rpath_list
binutils._rpath_clean = binutils._rpath_clean or binutils.rpath_clean
binutils._extractlib = binutils._extractlib or binutils.extractlib

-- generate c/c++ code from the binary file
function binutils.bin2c(binaryfile, outputfile, opt)
    opt = opt or {}
    if binutils._bin2c then
        return binutils._bin2c(binaryfile, outputfile, opt.linewidth or 32, opt.nozeroend or false)
    else
        -- fallback to old implementation if C implementation not available
        return nil, "bin2c: C implementation not available"
    end
end

-- generate object file from the binary file
-- @param binaryfile  the binary file path
-- @param outputfile  the output object file path
-- @param opt         the options
--                      - format: the object file format (coff, elf, macho), required
--                      - symbol_prefix: the symbol prefix (default: _binary_)
--                      - arch: the target architecture (default: x86_64)
--                      - plat: the target platform (default: macosx, only for macho)
--                      - basename: the base name for symbols
--                      - target_minver: the target minimum version (only for macho)
--                      - xcode_sdkver: the Xcode SDK version (only for macho)
--                      - zeroend: append null terminator (default: false)
function binutils.bin2obj(binaryfile, outputfile, opt)
    opt = opt or {}
    local format = opt.format
    if not format then
        -- auto-detect format based on host platform
        local host = os.host()
        if host == "windows" or host == "mingw" or host == "msys" or host == "cygwin" then
            format = "coff"
        elseif host == "macosx" or host == "iphoneos" or host == "watchos" or host == "appletvos" then
            format = "macho"
        else
            format = "elf"
        end
    end
    format = format:lower()

    if format == "coff" then
        if not binutils._bin2coff then
            return nil, "bin2obj: binutils._bin2coff not available (C implementation not compiled)"
        end
        return binutils._bin2coff(binaryfile, outputfile, opt.symbol_prefix or "_binary_", opt.arch or "x86_64", opt.basename, opt.zeroend or false)
    elseif format == "macho" then
        if not binutils._bin2macho then
            return nil, "bin2obj: binutils._bin2macho not available (C implementation not compiled)"
        end
        return binutils._bin2macho(binaryfile, outputfile, opt.symbol_prefix or "_binary_", opt.plat or "macosx", opt.arch or "x86_64", opt.basename, opt.target_minver, opt.xcode_sdkver, opt.zeroend or false)
    elseif format == "elf" then
        if not binutils._bin2elf then
            return nil, "bin2obj: binutils._bin2elf not available (C implementation not compiled)"
        end
        return binutils._bin2elf(binaryfile, outputfile, opt.symbol_prefix or "_binary_", opt.arch or "x86_64", opt.basename, opt.zeroend or false)
    else
        return nil, string.format("bin2obj: unsupported format '%s' (supported: coff, elf, macho)", format)
    end
end


-- read symbols from object file (auto-detect format: COFF, ELF, or Mach-O)
function binutils.readsyms(binaryfile)
    if binutils._readsyms then
        return binutils._readsyms(binaryfile)
    else
        return nil, "readsyms: C implementation not available"
    end
end

-- get dependent libraries from binary file (auto-detect format: COFF, ELF, or Mach-O)
function binutils.deplibs(binaryfile)
    if binutils._deplibs then
        return binutils._deplibs(binaryfile)
    else
        return nil, "deplibs: C implementation not available"
    end
end

-- get rpath list from binary file (auto-detect format: ELF or Mach-O)
function binutils.rpath_list(binaryfile)
    if binutils._rpath_list then
        return binutils._rpath_list(binaryfile)
    else
        return nil, "binutils: internal rpath_list not supported!"
    end
end

-- insert rpath to binary file (auto-detect format: ELF or Mach-O)

-- clean rpaths from binary file (auto-detect format: ELF or Mach-O)
function binutils.rpath_clean(binaryfile)
    if binutils._rpath_clean then
        return binutils._rpath_clean(binaryfile)
    else
        return false, "binutils: internal rpath_clean not supported!"
    end
end

-- extract static library to directory
-- Supports AR format (.a) and MSVC lib format (.lib)
-- @param libraryfile the static library file path (.a or .lib)
-- @param outputdir    the output directory to extract object files
-- @param opt          the options (optional)
--                       - plain: extract all object files to the same directory (default: true)
-- @return             true on success, false and error message on failure
function binutils.extractlib(libraryfile, outputdir, opt)
    if binutils._extractlib then
        local ok, errors = binutils._extractlib(libraryfile, outputdir, opt and opt.plain)
        if ok then
            return true
        else
            return false, errors or "extractlib: unknown error"
        end
    else
        return false, "extractlib: C implementation not available"
    end
end

-- return module
return binutils