A Go library for reading, writing, and manipulating glibc ld.so.cache files (the glibc-ld.so.cache1.1 format).
The ld.so.cache file is used by the dynamic linker (ld.so) to quickly locate shared libraries without searching the filesystem. This package can parse existing cache files, modify their entries, and generate new cache files compatible with glibc's dynamic linker.
Byte order is detected automatically when reading.
go get github.com/KarpelesLab/ldcache
ldso, err := ldcache.Open("/etc/ld.so.cache")
if err != nil {
log.Fatal(err)
}
for _, entry := range ldso.Entries {
fmt.Println(entry)
}ldso := ldcache.New()
ldso.Entries = append(ldso.Entries, &ldcache.Entry{
Flags: 0x0303, // libc6,x86-64
Key: "libfoo.so.1",
Value: "/usr/lib/libfoo.so.1.2.3",
})
sort.Sort(ldso.Entries)
err := ldso.SaveAs("/etc/ld.so.cache")After loading an ld.so.cache file, you can manipulate its Entries (add, remove, or filter), then generate a new file.
ldso, err := ldcache.Open("/etc/ld.so.cache")
if err != nil {
log.Fatal(err)
}
// Remove duplicates
ldso.Unique()
// Sort entries (required for the dynamic linker's binary search)
sort.Sort(ldso.Entries)
// Write to a new file
err = ldso.SaveAs("ld.so.cache")Entries must be sorted before writing if you added or reordered entries.
The dynamic linker (ld.so) uses binary search to look up libraries in the cache: it reads the entry in the middle, compares the name with what it's looking for, then continues into the first or second half accordingly. This narrows down the result in only a few reads instead of scanning the entire file. An unsorted cache will cause the binary search to miss entries, making libraries invisible to the linker even though they are present in the file.
The sort uses glibc's _dl_cache_libcmp algorithm, which compares numeric segments by value rather than lexicographically (e.g. .so.9 sorts before .so.10).
sort.Sort(ldso.Entries)Sorting may be skipped if you only removed entries without changing the relative order of the remaining ones.