aboutsummaryrefslogtreecommitdiff
path: root/lib/std/elf.zig
diff options
context:
space:
mode:
authorgeemili <opensource@geemili.xyz>2025-02-10 18:47:14 -0700
committerAndrew Kelley <andrew@ziglang.org>2025-02-22 17:33:49 -0500
commit6ef2384c07ef6817f134ffc61e34bcea6e87df92 (patch)
tree44b9690d032aea3d935762bef4b8cc064797f873 /lib/std/elf.zig
parentb7512c3e5d1734c301b8e5c1cda0385b0a967e0c (diff)
downloadzig-6ef2384c07ef6817f134ffc61e34bcea6e87df92.tar.gz
zig-6ef2384c07ef6817f134ffc61e34bcea6e87df92.zip
std.DynLib: add support for DT_GNU_HASH sections in elf files
Diffstat (limited to 'lib/std/elf.zig')
-rw-r--r--lib/std/elf.zig37
1 files changed, 37 insertions, 0 deletions
diff --git a/lib/std/elf.zig b/lib/std/elf.zig
index f326b6b5a9..28f7cc2482 100644
--- a/lib/std/elf.zig
+++ b/lib/std/elf.zig
@@ -2395,3 +2395,40 @@ pub const STRNAME = genSpecialMemberName("//");
pub const SYM64NAME = genSpecialMemberName("/SYM64/");
pub const SYMDEFNAME = genSpecialMemberName("__.SYMDEF");
pub const SYMDEFSORTEDNAME = genSpecialMemberName("__.SYMDEF SORTED");
+
+pub const gnu_hash = struct {
+
+ // See https://flapenguin.me/elf-dt-gnu-hash
+
+ pub const Header = extern struct {
+ nbuckets: u32,
+ symoffset: u32,
+ bloom_size: u32,
+ bloom_shift: u32,
+ };
+
+ pub const ChainEntry = packed struct(u32) {
+ end_of_chain: bool,
+ /// Contains the top bits of the hash value.
+ hash: u31,
+ };
+
+ /// Calculate the hash value for a name
+ pub fn calculate(name: []const u8) u32 {
+ var hash: u32 = 5381;
+
+ for (name) |char| {
+ hash = (hash << 5) +% hash +% char;
+ }
+
+ return hash;
+ }
+
+ test calculate {
+ try std.testing.expectEqual(0x00001505, calculate(""));
+ try std.testing.expectEqual(0x156b2bb8, calculate("printf"));
+ try std.testing.expectEqual(0x7c967e3f, calculate("exit"));
+ try std.testing.expectEqual(0xbac212a0, calculate("syscall"));
+ try std.testing.expectEqual(0x8ae9f18e, calculate("flapenguin.me"));
+ }
+};