aboutsummaryrefslogtreecommitdiff
path: root/src/link/plan9/a.out.zig
blob: daf4acc6eaadd5f82576b09d10a519c6363cdffa (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
// Copyright © 2021 Plan 9 Foundation
// Copyright © 20XX 9front authors

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// Idomatic translation of 9front a.out.h
const std = @import("std");
// all integers are in big-endian format (needs a byteswap)
pub const ExecHdr = extern struct {
    magic: u32,
    text: u32,
    data: u32,
    bss: u32,
    syms: u32,
    entry: u32,
    spsz: u32,
    pcsz: u32,
    comptime {
        std.debug.assert(@sizeOf(@This()) == 32);
    }
    /// it is up to the caller to disgard the last 8 bytes if the header is not fat
    pub fn toU8s(self: *@This()) [40]u8 {
        var buf: [40]u8 = undefined;
        var i: u8 = 0;
        inline for (std.meta.fields(@This())) |f| {
            std.mem.writeIntSliceBig(u32, buf[i .. i + 4], @field(self, f.name));
            i += 4;
        }
        return buf;
    }
};

// uchar value[8];
// char  type;
// char  name[n];   /* NUL-terminated */
pub const Sym = struct {
    value: u64, // big endian in the file
    type: SymType,
    name: []const u8,
};
// The type field is one of the following characters with the
// high bit set:
// T    text segment symbol
// t    static text segment symbol
// L    leaf function text segment symbol
// l    static leaf function text segment symbol
// D    data segment symbol
// d    static data segment symbol
// B    bss segment symbol
// b    static bss segment symbol
// a    automatic (local) variable symbol
// p    function parameter symbol
// f    source file name components
// z    source file name
// Z    source file line offset
// m for '.frame'
pub const SymType = enum(u8) {
    T = 0x80 | 'T',
    t = 0x80 | 't',
    L = 0x80 | 'L',
    l = 0x80 | 'l',
    D = 0x80 | 'D',
    d = 0x80 | 'd',
    B = 0x80 | 'B',
    b = 0x80 | 'b',
    a = 0x80 | 'a',
    p = 0x80 | 'p',
    f = 0x80 | 'f',
    z = 0x80 | 'z',
    Z = 0x80 | 'Z',
    m = 0x80 | 'm',
    pub fn toGlobal(self: SymType) SymType {
        return switch (self) {
            .t => .T,
            .b => .B,
            .d => .D,
            else => unreachable,
        };
    }
};

pub const HDR_MAGIC = 0x00008000;
pub inline fn _MAGIC(f: anytype, b: anytype) @TypeOf(f | ((((@as(c_int, 4) * b) + @as(c_int, 0)) * b) + @as(c_int, 7))) {
    return f | ((((@as(c_int, 4) * b) + @as(c_int, 0)) * b) + @as(c_int, 7));
}
pub const A_MAGIC = _MAGIC(0, 8); // 68020
pub const I_MAGIC = _MAGIC(0, 11); // intel 386
pub const J_MAGIC = _MAGIC(0, 12); // intel 960 (retired)
pub const K_MAGIC = _MAGIC(0, 13); // sparc
pub const V_MAGIC = _MAGIC(0, 16); // mips 3000 BE
pub const X_MAGIC = _MAGIC(0, 17); // att dsp 3210 (retired)
pub const M_MAGIC = _MAGIC(0, 18); // mips 4000 BE
pub const D_MAGIC = _MAGIC(0, 19); // amd 29000 (retired)
pub const E_MAGIC = _MAGIC(0, 20); // arm
pub const Q_MAGIC = _MAGIC(0, 21); // powerpc
pub const N_MAGIC = _MAGIC(0, 22); // mips 4000 LE
pub const L_MAGIC = _MAGIC(0, 23); // dec alpha (retired)
pub const P_MAGIC = _MAGIC(0, 24); // mips 3000 LE
pub const U_MAGIC = _MAGIC(0, 25); // sparc64
pub const S_MAGIC = _MAGIC(HDR_MAGIC, 26); // amd64
pub const T_MAGIC = _MAGIC(HDR_MAGIC, 27); // powerpc64
pub const R_MAGIC = _MAGIC(HDR_MAGIC, 28); // arm64

pub fn magicFromArch(arch: std.Target.Cpu.Arch) !u32 {
    return switch (arch) {
        .i386 => I_MAGIC,
        .sparc => K_MAGIC, // TODO should sparcv9 and sparcel go here?
        .mips => V_MAGIC,
        .arm => E_MAGIC,
        .aarch64 => R_MAGIC,
        .powerpc => Q_MAGIC,
        .powerpc64 => T_MAGIC,
        .x86_64 => S_MAGIC,
        else => error.ArchNotSupportedByPlan9,
    };
}