zig/tools/gen_stubs.zig
Isaac Freund 343249efd8 stage2: use %type not @type for libc stubs
Apparently ARM uses @ for comments. Everything seems to accept % here
though.
2020-12-13 23:19:23 -05:00

118 lines
3.5 KiB
Zig

const std = @import("std");
const mem = std.mem;
const Symbol = struct {
name: []const u8,
section: []const u8,
kind: enum {
global,
weak,
},
type: enum {
none,
function,
object,
},
protected: bool,
};
// Example usage:
// objdump --dynamic-syms /path/to/libc.so | ./gen_stubs > lib/libc/musl/libc.s
pub fn main() !void {
const stdin = std.io.getStdIn().reader();
const stdout = std.io.getStdOut().writer();
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const ally = &arena.allocator;
var symbols = std.ArrayList(Symbol).init(ally);
var sections = std.ArrayList([]const u8).init(ally);
// This is many times larger than any line objdump produces should ever be
var buf: [4096]u8 = undefined;
// Sample input line:
// 00000000000241b0 g DF .text 000000000000001b copy_file_range
while (try stdin.readUntilDelimiterOrEof(&buf, '\n')) |line| {
// the lines we want all start with a 16 digit hex value
if (line.len < 16) continue;
_ = std.fmt.parseInt(u64, line[0..16], 16) catch continue;
// Ignore non-dynamic symbols
if (line[22] != 'D') continue;
const section = line[25 .. 25 + mem.indexOfAny(u8, line[25..], &std.ascii.spaces).?];
// the last whitespace-separated column is the symbol name
const name = line[1 + mem.lastIndexOfAny(u8, line, &std.ascii.spaces).? ..];
const symbol = Symbol{
.name = try ally.dupe(u8, name),
.section = try ally.dupe(u8, section),
.kind = if (line[17] == 'g' and line[18] == ' ')
.global
else if (line[17] == ' ' and line[18] == 'w')
.weak
else
unreachable,
.type = switch (line[23]) {
'F' => .function,
'O' => .object,
' ' => .none,
else => unreachable,
},
.protected = mem.indexOf(u8, line, ".protected") != null,
};
for (sections.items) |s| {
if (mem.eql(u8, s, symbol.section)) break;
} else {
try sections.append(symbol.section);
}
try symbols.append(symbol);
}
std.sort.sort(Symbol, symbols.items, {}, cmpSymbols);
std.sort.sort([]const u8, sections.items, {}, alphabetical);
for (sections.items) |section| {
try stdout.print("{s}\n", .{section});
for (symbols.items) |symbol| {
if (!mem.eql(u8, symbol.section, section)) continue;
switch (symbol.kind) {
.global => try stdout.print(".globl {s}\n", .{symbol.name}),
.weak => try stdout.print(".weak {s}\n", .{symbol.name}),
}
switch (symbol.type) {
.function => try stdout.print(".type {s}, %function;\n", .{symbol.name}),
.object => try stdout.print(".type {s}, @object;\n", .{symbol.name}),
.none => {},
}
if (symbol.protected)
try stdout.print(".protected {s}\n", .{symbol.name});
try stdout.print("{s}:\n", .{symbol.name});
}
}
}
fn cmpSymbols(_: void, lhs: Symbol, rhs: Symbol) bool {
return alphabetical({}, lhs.name, rhs.name);
}
fn alphabetical(_: void, lhs: []const u8, rhs: []const u8) bool {
var i: usize = 0;
while (i < lhs.len and i < rhs.len) : (i += 1) {
if (lhs[i] == rhs[i]) continue;
return lhs[i] < rhs[i];
}
return lhs.len < rhs.len;
}