authorgravatar for 35903594+patrickwick@users.noreply.github.comPatrick Wickenhaeuser <35903594+patrickwick@users.noreply.github.com> 2024-10-04 12:38:34+02:00
committergravatar for 35903594+patrickwick@users.noreply.github.comPatrick Wickenhaeuser <35903594+patrickwick@users.noreply.github.com> 2024-10-04 15:49:50+02:00
log8cd7a9e5fc0be2328388acb138ccce77a45603bc
treed499a628bb8cde7765332a8f3287842aa9633966
parentcaa699fc68bcdc3c5e80eb089d8af62000e06757

19009: zig objcopy: parse section flags


1 files changed, 96 insertions(+), 0 deletions(-)

lib/compiler/objcopy.zig+96
...@@ -125,6 +125,8 @@ fn cmdObjCopy(...@@ -125,6 +125,8 @@ fn cmdObjCopy(
125 if (i >= args.len) fatal("expected section name and filename arguments after '{s}'", .{arg});125 if (i >= args.len) fatal("expected section name and filename arguments after '{s}'", .{arg});
126126
127 if (splitOption(args[i])) |split| {127 if (splitOption(args[i])) |split| {
128 const flags = parseSectionFlags(split.second);
129 _ = flags; // TODO: 19009: integrate
128 set_section_flags = .{ .section_name = split.first, .flags = split.second };130 set_section_flags = .{ .section_name = split.first, .flags = split.second };
129 } else {131 } else {
130 fatal("unrecognized argument: '{s}', expecting <name>=<flags>", .{args[i]});132 fatal("unrecognized argument: '{s}', expecting <name>=<flags>", .{args[i]});
...@@ -1533,6 +1535,100 @@ const ElfFileHelper = struct {...@@ -1533,6 +1535,100 @@ const ElfFileHelper = struct {
1533 }1535 }
1534};1536};
15351537
1538/// Supporting a subset of GNU and LLVM objcopy for ELF only
1539/// GNU:
1540/// alloc: add SHF_ALLOC
1541/// contents: if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing
1542/// load: if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing
1543/// noload: not supported
1544/// readonly: clear default SHF_WRITE flag
1545/// code: add SHF_EXECINSTR
1546/// data: not supported
1547/// rom: not supported
1548/// exclude: add SHF_EXCLUDE
1549/// share: not supported
1550/// debug: not supported
1551/// large: add SHF_X86_64_LARGE. Fatal error if target is not x86_64
1552///
1553/// LLVM:
1554/// merge: add SHF_MERGE
1555/// strings: add SHF_STRINGS
1556const SectionFlags = packed struct {
1557 alloc: bool = false,
1558 contents: bool = false,
1559 load: bool = false,
1560 noload: bool = false,
1561 readonly: bool = false,
1562 code: bool = false,
1563 data: bool = false,
1564 rom: bool = false,
1565 exclude: bool = false,
1566 shared: bool = false,
1567 debug: bool = false,
1568 large: bool = false,
1569 merge: bool = false,
1570 strings: bool = false,
1571};
1572
1573fn parseSectionFlags(comma_separated_flags: []const u8) SectionFlags {
1574 const P = struct {
1575 fn parse(flags: *SectionFlags, string: []const u8) void {
1576 if (string.len == 0) return;
1577
1578 if (std.mem.eql(u8, string, "alloc")) {
1579 flags.alloc = true;
1580 } else if (std.mem.eql(u8, string, "contents")) {
1581 flags.contents = true;
1582 } else if (std.mem.eql(u8, string, "load")) {
1583 flags.load = true;
1584 } else if (std.mem.eql(u8, string, "noload")) {
1585 flags.noload = true;
1586 } else if (std.mem.eql(u8, string, "readonly")) {
1587 flags.readonly = true;
1588 } else if (std.mem.eql(u8, string, "code")) {
1589 flags.code = true;
1590 } else if (std.mem.eql(u8, string, "data")) {
1591 flags.data = true;
1592 } else if (std.mem.eql(u8, string, "rom")) {
1593 flags.rom = true;
1594 } else if (std.mem.eql(u8, string, "exclude")) {
1595 flags.exclude = true;
1596 } else if (std.mem.eql(u8, string, "shared")) {
1597 flags.shared = true;
1598 } else if (std.mem.eql(u8, string, "debug")) {
1599 flags.debug = true;
1600 } else if (std.mem.eql(u8, string, "large")) {
1601 flags.large = true;
1602 } else if (std.mem.eql(u8, string, "merge")) {
1603 flags.merge = true;
1604 } else if (std.mem.eql(u8, string, "strings")) {
1605 flags.strings = true;
1606 } else {
1607 std.log.err("Skipping unrecognized section flag '{s}'", .{string});
1608 }
1609 }
1610 };
1611
1612 var flags = SectionFlags{};
1613 var start: usize = 0;
1614 for (comma_separated_flags, 0..) |c, i| {
1615 if (c == ',') {
1616 defer start = i + 1;
1617 const string = comma_separated_flags[start..i];
1618 P.parse(&flags, string);
1619 }
1620 }
1621 P.parse(&flags, comma_separated_flags[start..]);
1622 return flags;
1623}
1624
1625test "Parse section flags" {
1626 const F = SectionFlags;
1627 try std.testing.expectEqual(F{}, parseSectionFlags(""));
1628 try std.testing.expectEqual(F{ .alloc = true }, parseSectionFlags("alloc"));
1629 try std.testing.expectEqual(F{ .alloc = true, .code = true }, parseSectionFlags("alloc,code"));
1630}
1631
1536const SplitResult = struct { first: []const u8, second: []const u8 };1632const SplitResult = struct { first: []const u8, second: []const u8 };
15371633
1538fn splitOption(option: []const u8) ?SplitResult {1634fn splitOption(option: []const u8) ?SplitResult {