mirror of
https://github.com/ziglang/zig.git
synced 2024-12-04 19:09:32 +00:00
343249efd8
Apparently ARM uses @ for comments. Everything seems to accept % here though.
118 lines
3.5 KiB
Zig
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;
|
|
}
|