aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-07-08 14:24:16 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-07-08 14:24:16 -0700
commit476faef97ab0f292159bb3eef42078f9b1e43dde (patch)
treefdbe0ebed92520fa7920409cc65c9b51ca9dd288 /src/link
parent4eb778fc3eeec62c5c45ccc0a21631ff757d8a23 (diff)
downloadzig-476faef97ab0f292159bb3eef42078f9b1e43dde.tar.gz
zig-476faef97ab0f292159bb3eef42078f9b1e43dde.zip
plan9 cleanups
* rename files to adhere to conventions * remove unnecessary function / optionality * fix merge conflict * better panic message * remove unnecessary TODO comment * proper namespacing of declarations * clean up documentation comments * no copyright header needed for a brand new zig file that is not copied from anywhere
Diffstat (limited to 'src/link')
-rw-r--r--src/link/Plan9.zig13
-rw-r--r--src/link/Plan9/aout.zig114
-rw-r--r--src/link/plan9/a.out.zig134
3 files changed, 121 insertions, 140 deletions
diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig
index f12b8af6b5..f880b40d85 100644
--- a/src/link/Plan9.zig
+++ b/src/link/Plan9.zig
@@ -1,10 +1,13 @@
+//! This implementation does all the linking work in flush(). A future improvement
+//! would be to add incremental linking in a similar way as ELF does.
+
const Plan9 = @This();
const std = @import("std");
const link = @import("../link.zig");
const Module = @import("../Module.zig");
const Compilation = @import("../Compilation.zig");
-const aout = @import("plan9/a.out.zig");
+const aout = @import("Plan9/aout.zig");
const codegen = @import("../codegen.zig");
const trace = @import("../tracy.zig").trace;
const mem = std.mem;
@@ -14,8 +17,6 @@ const Allocator = std.mem.Allocator;
const log = std.log.scoped(.link);
const assert = std.debug.assert;
-// TODO use incremental compilation
-
base: link.File,
sixtyfour_bit: bool,
error_flags: File.ErrorFlags = File.ErrorFlags{},
@@ -38,7 +39,7 @@ const Bases = struct {
data: u64,
};
-fn getAddr(self: Plan9, addr: u64, t: aout.SymType) u64 {
+fn getAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 {
return addr + switch (t) {
.T, .t, .l, .L => self.bases.text,
.D, .d, .B, .b => self.bases.data,
@@ -46,7 +47,7 @@ fn getAddr(self: Plan9, addr: u64, t: aout.SymType) u64 {
};
}
/// opposite of getAddr
-fn takeAddr(self: Plan9, addr: u64, t: aout.SymType) u64 {
+fn takeAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 {
return addr - switch (t) {
.T, .t, .l, .L => self.bases.text,
.D, .d, .B, .b => self.bases.data,
@@ -59,7 +60,7 @@ fn getSymAddr(self: Plan9, s: aout.Sym) u64 {
}
pub const DeclBlock = struct {
- type: aout.SymType,
+ type: aout.Sym.Type,
/// offset in the text or data sects
offset: ?u64,
/// offset into syms
diff --git a/src/link/Plan9/aout.zig b/src/link/Plan9/aout.zig
new file mode 100644
index 0000000000..f6dff7437c
--- /dev/null
+++ b/src/link/Plan9/aout.zig
@@ -0,0 +1,114 @@
+const std = @import("std");
+const assert = std.debug.assert;
+
+/// 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,
+ /// You should truncate this to 32 bits on 64 bit systems, then but the actual 8 bytes
+ /// in the fat header.
+ entry: u32,
+ spsz: u32,
+ pcsz: u32,
+ comptime {
+ 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;
+ }
+};
+
+pub const Sym = struct {
+ /// Big endian in the file
+ value: u64,
+ type: Type,
+ 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 Type = 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: Type) Type {
+ 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,
+ };
+}
diff --git a/src/link/plan9/a.out.zig b/src/link/plan9/a.out.zig
deleted file mode 100644
index 85be2d5c36..0000000000
--- a/src/link/plan9/a.out.zig
+++ /dev/null
@@ -1,134 +0,0 @@
-// 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,
- /// You should truncate this to 32 bits on 64 bit systems, then but the actual 8 bytes
- /// in the fat header.
- 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,
- };
-}