Created
March 19, 2021 00:02
-
-
Save ikskuh/65e7a158a600a94dad22ab5a15be080f to your computer and use it in GitHub Desktop.
linkerscript.zig
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
/// The linker here is "preloaded" with all input object files / symbols. | |
/// After this function is run, the linker will resolve all symbol references | |
/// and print all unassigned symbols (\u2192 error) | |
pub fn link(l: *std.link.Linker) !void { | |
// Creates a new output section that will be loaded into the | |
// same address as its virtual address. It's also a (rx!w) section | |
const dot_text = l.createOutputSection(".text", .{ | |
.read = true, | |
.execute = true, | |
.write = false, | |
.load_address = .virtual_address, | |
.virtual_address = 0x0000_0000, | |
}); | |
{ | |
// Search all symbols that match a given filter (in this case "are in section .text") | |
var iter = l.findSymbols(.{ .section = ".text" }); | |
while (iter.next()) |sym| { | |
dot_text.append(sym); | |
} | |
} | |
// Assert we have at least our first 8 interrupt vectors | |
std.debug.assert(dot_text.length > 8 * 4); | |
// Compute the checksum in the interrupt vector table, | |
// this is an inplace modification of the section data | |
{ | |
var checksum: u32 = 0; | |
var i: usize = 0; | |
while (i < 7) : (i += 1) { | |
checksum -%= std.mem.readIntLittle(u32, dot_text.data[4 * i ..][0..4]); | |
} | |
std.mem.writeIntLittle(u32, dot_data.data[28..32], checksum); | |
} | |
// Put .data behind .text in the flash memory | |
// This section will be loaded into a different memory area than the one it is linked to. | |
const dot_data = l.createOutputSection(".data", .{ | |
.read = true, | |
.execute = false, | |
.write = true, | |
.load_address = .{ .fixed = dot_text.length }, // Load the .data section directly behind .text into flash | |
.virtual_address = 0x1000_0000, | |
}); | |
// Same as the loop above, will just add all symbols that match the filter | |
dot_data.appendAll(.{ .section = ".data" }); | |
// Assert that .text + .data fit in the flash and don't exceed total flash size | |
std.debug.assert(dot_text.length + dot_data.length <= 512 * 1024); | |
// Put .data behind .text in the flash memory | |
const dot_bss = l.createOutputSection(".bss", .{ | |
.read = true, | |
.execute = false, | |
.write = true, | |
.load_address = .zero_init, // Sets the section to not be loaded in the final artifact (zero init) | |
.virtual_address = dot_data.virtual_address + dot_data.length, // Section is located *behind* .data | |
}); | |
// Same as the loop above, will just add all symbols that match the filter | |
dot_bss.appendAll(.{ .section = ".bss" }); | |
// Assert that .text + .bss fit into the lower RAM | |
std.debug.assert(dot_data.length + dot_bss.length < 32 * 1024); | |
// Set/store our entry point in the output file | |
if (l.findSymbol("_start")) |sym| { | |
l.setEntryPoint(sym.address.?); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment