From 9c2d62257de9d2f38ee400685ea297aec0ce6075 Mon Sep 17 00:00:00 2001 From: Dongdong Tao Date: Thu, 14 May 2026 17:30:24 +0900 Subject: [PATCH 01/13] version_utils: add get_elf_build_id and get_host_arch helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two libelf-based helpers that the embedded DWARF lookup will use as its new key material: std::string get_elf_build_id(const std::string& path); std::string get_host_arch(); get_elf_build_id walks the ELF .note.gnu.build-id section and hex-encodes the note descriptor. Doesn't validate descriptor length (GNU ld emits 160-bit SHA1, LLD's xxhash variant is 128-bit) — just encodes whatever bytes are there. Returns empty string on any failure (unreadable file, not an ELF, no build-id note) so callers can treat "no key available" as a soft signal to fall through to live DWARF parsing. get_host_arch normalises uname.machine to the dpkg --print-architecture naming convention (amd64, arm64, ppc64el, …) so values round-trip with package metadata and the existing files// directory layout. libelf is already linked into every cephtrace binary via the Makefile's LIBS := … -lelf; no build-system changes needed. --- src/version_utils.cc | 81 ++++++++++++++++++++++++++++++++++++++++++++ src/version_utils.h | 30 ++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/src/version_utils.cc b/src/version_utils.cc index f19b212..7042e01 100644 --- a/src/version_utils.cc +++ b/src/version_utils.cc @@ -12,6 +12,9 @@ #include #include #include +#include +#include +#include #include "nlohmann/json.hpp" using json = nlohmann::json; @@ -514,6 +517,84 @@ bool check_executable_deleted(int process_id, const std::string& exe_name) { return false; } +std::string get_elf_build_id(const std::string& path) { + if (elf_version(EV_CURRENT) == EV_NONE) { + return ""; + } + + int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC); + if (fd < 0) { + return ""; + } + + Elf* elf = elf_begin(fd, ELF_C_READ, nullptr); + if (!elf) { + close(fd); + return ""; + } + + std::string result; + size_t shstrndx = 0; + + if (elf_getshdrstrndx(elf, &shstrndx) != 0) { + elf_end(elf); + close(fd); + return ""; + } + + // Walk SHT_NOTE sections, look for ".note.gnu.build-id". This is + // typically the only build-id note in cephtrace's target binaries; if + // the binary was unusually stripped to PT_NOTE-only the lookup will + // miss and the caller falls back to live DWARF parsing — that's fine. + for (Elf_Scn* scn = elf_nextscn(elf, nullptr); scn != nullptr; + scn = elf_nextscn(elf, scn)) { + GElf_Shdr shdr; + if (gelf_getshdr(scn, &shdr) != &shdr) continue; + if (shdr.sh_type != SHT_NOTE) continue; + + const char* name = elf_strptr(elf, shstrndx, shdr.sh_name); + if (!name || strcmp(name, ".note.gnu.build-id") != 0) continue; + + Elf_Data* data = elf_getdata(scn, nullptr); + if (!data || !data->d_buf) continue; + + size_t off = 0, name_off = 0, desc_off = 0; + GElf_Nhdr nhdr; + while ((off = gelf_getnote(data, off, &nhdr, &name_off, &desc_off)) > 0) { + if (nhdr.n_type != NT_GNU_BUILD_ID) continue; + const unsigned char* desc = + static_cast(data->d_buf) + desc_off; + char hex[3]; + result.reserve(nhdr.n_descsz * 2); + for (size_t i = 0; i < nhdr.n_descsz; ++i) { + std::snprintf(hex, sizeof(hex), "%02x", desc[i]); + result += hex; + } + break; + } + if (!result.empty()) break; + } + + elf_end(elf); + close(fd); + return result; +} + +std::string get_host_arch() { + struct utsname u; + if (uname(&u) != 0) return ""; + std::string m = u.machine; + // Match dpkg --print-architecture's naming so values round-trip with + // package metadata and with the existing per-distro file layout. + if (m == "x86_64") return "amd64"; + if (m == "aarch64") return "arm64"; + if (m == "ppc64le") return "ppc64el"; + if (m == "s390x") return "s390x"; + if (m == "armv7l" || m == "armv6l") return "armhf"; + if (m == "i686" || m == "i386") return "i386"; + return m; +} + void print_tool_version(const char* tool_name) { const std::string version = CEPHTRACE_VERSION; const std::string git_describe = CEPHTRACE_GIT_DESCRIBE; diff --git a/src/version_utils.h b/src/version_utils.h index 635df45..db1a448 100644 --- a/src/version_utils.h +++ b/src/version_utils.h @@ -97,6 +97,36 @@ bool is_ceph_version_squid_or_above(const std::string& version); */ std::string get_version_from_json(const std::string& json_file); +/** + * Read the GNU build-id from an ELF binary's `.note.gnu.build-id` section. + * + * Used as the lookup key for the embedded DWARF data registry. Build-id is + * unique per (source, toolchain, arch) build and is always present in + * non-stripped binaries — and even survives `strip` by default because the + * note lives in an allocated segment. + * + * @param path Absolute path to an ELF file. + * @return Hex-encoded build-id (typically 40 chars for GNU ld's 160-bit SHA1, + * 32 chars for LLD's xxhash variant), or empty string on any error + * (file unreadable, not an ELF, no build-id note). + */ +std::string get_elf_build_id(const std::string& path); + +/** + * Return the running host's architecture using `dpkg --print-architecture`'s + * naming convention so the value round-trips with package metadata: + * x86_64 → "amd64" + * aarch64 → "arm64" + * ppc64le → "ppc64el" + * s390x → "s390x" + * armv7l → "armhf" + * i686 → "i386" + * anything else → uname.machine verbatim + * + * @return Architecture string, or empty string if uname(2) fails. + */ +std::string get_host_arch(); + /** * Print the version banner for a cephtrace tool to stdout. * From 6eb9cb4c9138d53272e2ed78173781cbeeb702cf Mon Sep 17 00:00:00 2001 From: Dongdong Tao Date: Thu, 14 May 2026 17:31:54 +0900 Subject: [PATCH 02/13] dwarf_parser: remember full module paths in add_module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a public mod_path map (basename → full path on disk) populated in add_module(). Mirrors the existing public mod_func2pc / mod_func2vf maps in style and scope. Reason: the upcoming JSON schema includes a per-module build_id field, and export_to_json needs to read each module's ELF to compute its build-id. Today export_to_json only has access to module basenames (the keys of mod_func2pc / mod_func2vf) — no way to locate the file on disk. Stashing the full path at add_module() time, before any DWARF parsing happens, also avoids a TOCTOU window where the on-disk binary could be replaced (e.g. mid-upgrade) between parse and export. No call-site changes; mod_path is populated as a side effect of the existing add_module flow. --- src/dwarf_parser.cc | 6 +++++- src/dwarf_parser.h | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/dwarf_parser.cc b/src/dwarf_parser.cc index d8bdc35..fe021db 100644 --- a/src/dwarf_parser.cc +++ b/src/dwarf_parser.cc @@ -785,7 +785,11 @@ void DwarfParser::add_module(string path) { if (fd == -1) { cerr << "cannot open input file " << fname; } - + + // Remember the full path keyed by basename so export_to_json() can locate + // the on-disk ELF later for build-id extraction without re-resolving it. + mod_path[get_basename(path)] = path; + Dwfl *dwfl = create_dwfl(fd, fname); dwfls.push_back(dwfl); } diff --git a/src/dwarf_parser.h b/src/dwarf_parser.h index 32498c3..780d3f4 100644 --- a/src/dwarf_parser.h +++ b/src/dwarf_parser.h @@ -39,6 +39,10 @@ class DwarfParser { typedef std::map>> probes_t; mod_func2vf_t mod_func2vf; mod_func2pc_t mod_func2pc; + // basename → full path on disk for every add_module() call. Lets + // export_to_json() read each module's ELF build-id without the caller + // needing to re-derive the path. + std::map mod_path; global_mod_cu_type_cache_t global_type_cache; std::vector probe_units; probes_t probes; From 4a89d9b2c570ea50580408f02b7e9faf3590fc27 Mon Sep 17 00:00:00 2001 From: Dongdong Tao Date: Thu, 14 May 2026 17:32:59 +0900 Subject: [PATCH 03/13] dwarf_parser: write arch + per-module build_id in export_to_json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds two new fields to the exported JSON: - top-level "arch": uname.machine normalised to dpkg's naming (amd64, arm64, ppc64el, …) - per-module "build_id": the GNU build-id hex of the on-disk ELF that produced the func2pc / func2vf data for this module Both fields are written from the side-effect-free helpers added in the previous commit (get_host_arch, get_elf_build_id) so the export step gains no new I/O failure modes beyond what add_module already performed. build_id is omitted if mod_path lacks an entry for the module (e.g. the parser's data was loaded via import_from_json rather than add_module + parse). The downstream embedded loader will treat empty build_id as "never matches", so legacy JSONs round-tripped through this code stay inert to the new build-id lookup path. --- src/dwarf_parser.cc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/dwarf_parser.cc b/src/dwarf_parser.cc index fe021db..a3e2063 100644 --- a/src/dwarf_parser.cc +++ b/src/dwarf_parser.cc @@ -30,6 +30,7 @@ extern "C" { #include "dwarf_parser.h" #include "embedded_dwarf_data.h" #include "utils.h" +#include "version_utils.h" using namespace std; @@ -813,11 +814,31 @@ void DwarfParser::export_to_json(const std::string& filename, const std::string& j["version"] = version; } + // Record the host architecture so the consumer can refuse the JSON on a + // mismatched target (build-id keying is per-arch by construction, but + // tooling that looks at the file as data still benefits from the field). + std::string arch = get_host_arch(); + if (!arch.empty()) { + j["arch"] = arch; + } + // Convert both maps to JSON structure for (const auto& mod_pair : mod_func2vf) { const std::string& module = mod_pair.first; json module_obj; + // Read the on-disk ELF build-id for this module. mod_path is + // populated by add_module(); empty if the JSON was loaded from a + // file (export-then-export round-trip), in which case we cannot + // compute a build-id and the field is omitted. + auto path_it = mod_path.find(module); + if (path_it != mod_path.end()) { + std::string bid = get_elf_build_id(path_it->second); + if (!bid.empty()) { + module_obj["build_id"] = bid; + } + } + // Add function addresses (mod_func2pc) json pc_obj; if (mod_func2pc.count(module) > 0) { From 0c94328cd0e8dbe34874a582c5e230354c3819dc Mon Sep 17 00:00:00 2001 From: Dongdong Tao Date: Thu, 14 May 2026 17:33:33 +0900 Subject: [PATCH 04/13] dwarf_parser: future-proof import_from_json module iteration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The loop iterating top-level JSON keys to populate mod_func2pc / mod_func2vf used to skip a hard-coded "version" entry, which would silently treat new metadata fields (arch, future additions) as if they were modules — populating empty entries in the maps and noising up fill_map_hprobes downstream. Replace the hard-coded skip with a positive predicate: only iterate keys whose value is an object containing func2pc or func2vf. Adding new top-level metadata (arch, build_id, etc.) no longer requires updating this loop. --- src/dwarf_parser.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/dwarf_parser.cc b/src/dwarf_parser.cc index a3e2063..f1756f6 100644 --- a/src/dwarf_parser.cc +++ b/src/dwarf_parser.cc @@ -934,11 +934,17 @@ bool DwarfParser::import_from_json(const std::string& filename, const std::strin // Parse JSON structure for (const auto& [module, module_data] : j.items()) { - // Skip the version field as it's not a module - if (module == "version") { + // Skip top-level metadata (version, arch, future additions). + // Only iterate entries that look like module objects, i.e. have + // func2pc and/or func2vf children. More robust than a hard-coded + // skip-list as new metadata fields are added. + if (!module_data.is_object()) { continue; } - + if (!module_data.contains("func2pc") && !module_data.contains("func2vf")) { + continue; + } + // Convert absolute path to basename for backward compatibility // Legacy JSON files use full paths (e.g., "/usr/bin/ceph-osd") // New code expects basenames (e.g., "ceph-osd") From 6c2450bda8e7be0a46a7e9e6e4757e8cdbb06129 Mon Sep 17 00:00:00 2001 From: Dongdong Tao Date: Thu, 14 May 2026 17:35:24 +0900 Subject: [PATCH 05/13] generate_embedded_dwarf.py: emit arch + per-module build_id fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extends the generated EmbeddedModule / EmbeddedVersion C structs and their initializers to carry the two new metadata fields that DwarfParser::export_to_json now writes: struct EmbeddedModule { …; const char* build_id; … }; struct EmbeddedVersion { …; const char* arch; … }; Both fall back to an empty string when the source JSON lacks the field. Legacy JSONs without arch / build_id therefore round-trip through the generator unchanged on disk and produce empty values in the embedded arrays, which the runtime matcher will treat as never-matches once the key switches from version to build-id. Also factors a shared is_module_entry() predicate so analyze_limits and generate_version_entry stop using a hard-coded "skip the version key" heuristic that would silently treat new metadata keys as modules. --- tools/generate_embedded_dwarf.py | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/tools/generate_embedded_dwarf.py b/tools/generate_embedded_dwarf.py index 51bc48f..f60965d 100644 --- a/tools/generate_embedded_dwarf.py +++ b/tools/generate_embedded_dwarf.py @@ -38,6 +38,18 @@ def load_json_files(base_dir): return osdtrace, radostrace +def is_module_entry(val): + """Return True if a top-level JSON value looks like a module entry. + + Top-level keys in the per-version JSON are either metadata + (``version``, ``arch``, future additions) or per-module dicts that + contain ``func2pc`` / ``func2vf``. This predicate identifies the + latter so the rest of the generator doesn't need a hard-coded + metadata-key skip-list. + """ + return isinstance(val, dict) and ("func2pc" in val or "func2vf" in val) + + def analyze_limits(all_data): """Find maximum array sizes needed across all JSON files.""" max_modules = 0 @@ -47,8 +59,8 @@ def analyze_limits(all_data): for data in all_data: num_modules = 0 - for key, val in data.items(): - if key == "version": + for _key, val in data.items(): + if not is_module_entry(val): continue num_modules += 1 if "func2pc" in val: @@ -102,6 +114,10 @@ def _generate_module(mod_name, mod_data, indent): lines = [] lines.append(f'{indent} {{ // module: {mod_name}') lines.append(f'{indent} {_c_str(mod_name)},') + # Per-module ELF build-id (empty for legacy JSONs that pre-date the + # build-id keying scheme; the embedded loader treats "" as + # never-matches so legacy entries stay inert to the new lookup path). + lines.append(f'{indent} {_c_str(mod_data.get("build_id", ""))},') func2pc = mod_data.get("func2pc", {}) lines.append(f'{indent} {len(func2pc)}, // num_func2pc') @@ -134,12 +150,15 @@ def _generate_module(mod_name, mod_data, indent): def generate_version_entry(data, indent=" "): """Generate C++ initializer for one version entry.""" version = data.get("version", "unknown") + arch = data.get("arch", "") lines = [f'{indent}{{'] lines.append(f'{indent} {_c_str(version)},') + # Per-version target architecture (empty for legacy JSONs). + lines.append(f'{indent} {_c_str(arch)},') modules = [ (os.path.basename(k), v) - for k, v in data.items() if k != "version" + for k, v in data.items() if is_module_entry(v) ] lines.append(f'{indent} {len(modules)}, // num_modules') @@ -201,6 +220,7 @@ def generate_header(osdtrace, radostrace, limits): struct EmbeddedModule {{ const char* module_name; + const char* build_id; // Hex-encoded GNU build-id; "" for legacy entries. int num_func2pc; EmbeddedFuncPC func2pc[EMB_MAX_FUNCS]; int num_func2vf; @@ -209,6 +229,7 @@ def generate_header(osdtrace, radostrace, limits): struct EmbeddedVersion {{ const char* version; + const char* arch; // dpkg --print-architecture style; "" for legacy entries. int num_modules; EmbeddedModule modules[EMB_MAX_MODULES]; }}; From 4fbca886cdc646704d7a67628aec8bf728e0683d Mon Sep 17 00:00:00 2001 From: Dongdong Tao Date: Thu, 14 May 2026 17:39:17 +0900 Subject: [PATCH 06/13] dwarf_parser: key embedded DWARF lookup by ELF build-id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switches DwarfParser::import_from_embedded() from version-string keying (dpkg/rpm shell-out, host-namespace bound, arch-blind) to ELF GNU build-id keying (read from the target's .note.gnu.build-id, namespace- agnostic, arch-specific by construction). New signature: bool import_from_embedded( const std::vector>& modules, const std::string& trace_type, std::string* matched_version_out = nullptr); An entry matches iff its modules[] set equals the caller's (basename, build-id) set exactly. Any empty build-id on either side disqualifies that entry — legacy JSONs predating the build-id scheme therefore never match, falling cleanly through to live DWARF parsing. For osdtrace there is one (basename, build-id) pair (ceph-osd). For radostrace there are three (librbd.so.1, librados.so.2, libceph-common.so.2); all three build-ids must match the same embedded entry so we never silently load a JSON whose libraries don't agree. radostrace's squid-or-above struct-offset gate previously called get_package_version() directly; it now consumes the matched embedded entry's version string via the matched_version_out parameter, removing the need for a second dpkg shell-out on the fast path. Live-parse and -i/--import-json paths still use get_package_version / get_version_from_json respectively — the dpkg/rpm path is preserved for those. osdtrace and radostrace call-site updates included in the same commit because they're inseparable from the new signature. Closes the three known correctness failure modes of version-keying: - snap/container deployments (host dpkg returns wrong version) - cross-architecture (x86 JSON silently loaded on arm64) - custom rebuilds at same version string --- src/dwarf_parser.cc | 56 +++++++++++++++++++++++++++++++++++++++++---- src/dwarf_parser.h | 29 +++++++++++++++++++---- src/osdtrace.cc | 11 +++++---- src/radostrace.cc | 33 +++++++++++++++++++++----- 4 files changed, 109 insertions(+), 20 deletions(-) diff --git a/src/dwarf_parser.cc b/src/dwarf_parser.cc index f1756f6..ea8b6c2 100644 --- a/src/dwarf_parser.cc +++ b/src/dwarf_parser.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -999,7 +1000,10 @@ bool DwarfParser::import_from_json(const std::string& filename, const std::strin } } -bool DwarfParser::import_from_embedded(const std::string& expected_version, const std::string& trace_type) { +bool DwarfParser::import_from_embedded( + const std::vector>& modules, + const std::string& trace_type, + std::string* matched_version_out) { const EmbeddedVersion* versions = nullptr; int count = 0; @@ -1014,11 +1018,40 @@ bool DwarfParser::import_from_embedded(const std::string& expected_version, cons return false; } - // Find matching version + // Build the caller's (basename, build-id) set. An empty build-id on + // the caller side means we couldn't read the note from the target + // binary (snap-mounted readonly squashfs that lacks one, stripped + // image, etc.) — refuse the lookup in that case so we don't accept a + // partial match against an embedded entry whose own build-id is also + // empty (legacy JSON). + std::set> want; + for (const auto& m : modules) { + if (m.second.empty()) { + return false; + } + want.emplace(m.first, m.second); + } + if (want.empty()) { + return false; + } + + // Linear scan: an entry matches iff its modules[] set equals `want` + // exactly. Any empty build-id in the embedded data disqualifies that + // entry (legacy JSONs predating the build-id scheme). const EmbeddedVersion* match = nullptr; for (int i = 0; i < count; ++i) { - if (expected_version == versions[i].version) { - match = &versions[i]; + const EmbeddedVersion& v = versions[i]; + if (static_cast(v.num_modules) != want.size()) continue; + + bool all_match = true; + for (int m = 0; m < v.num_modules; ++m) { + const char* bid = v.modules[m].build_id; + if (!bid || *bid == '\0') { all_match = false; break; } + auto it = want.find({v.modules[m].module_name, bid}); + if (it == want.end()) { all_match = false; break; } + } + if (all_match) { + match = &v; break; } } @@ -1027,7 +1060,16 @@ bool DwarfParser::import_from_embedded(const std::string& expected_version, cons return false; } - std::clog << "Found embedded DWARF data for version: " << expected_version << std::endl; + // Log every matched module's (basename, build-id) so failures further + // downstream can be correlated with the exact embedded entry used. + std::clog << "Found embedded DWARF data (version " + << (match->version ? match->version : "?") + << ", arch " << (match->arch && *match->arch ? match->arch : "unspecified") + << "):" << std::endl; + for (int m = 0; m < match->num_modules; ++m) { + std::clog << " " << match->modules[m].module_name + << " build-id " << match->modules[m].build_id << std::endl; + } // Clear existing data mod_func2pc.clear(); @@ -1068,6 +1110,10 @@ bool DwarfParser::import_from_embedded(const std::string& expected_version, cons } } + if (matched_version_out && match->version) { + *matched_version_out = match->version; + } + return true; } diff --git a/src/dwarf_parser.h b/src/dwarf_parser.h index 780d3f4..8432557 100644 --- a/src/dwarf_parser.h +++ b/src/dwarf_parser.h @@ -101,12 +101,31 @@ class DwarfParser { */ bool import_from_json(const std::string& filename, const std::string& expected_version = ""); /** - * Imports module function data from compiled-in embedded DWARF data - * @param expected_version Version string to match against embedded data - * @param trace_type "osdtrace" or "radostrace" - * @return bool Returns true if a matching version was found and imported + * Imports module function data from compiled-in embedded DWARF data, + * matching the target binary by ELF GNU build-id. + * + * An embedded entry matches iff the set of (module basename, build-id) + * pairs the caller supplies equals the entry's `modules[]` set exactly + * (same size, same content). Any empty build-id on either side + * prevents that entry from matching — legacy JSONs without build-id + * data are therefore never selected by this path. + * + * @param modules Vector of (basename, hex-encoded build-id) + * pairs identifying the target binaries. + * For osdtrace: {{"ceph-osd", }}. + * For radostrace: three entries (librbd.so.1, + * librados.so.2, libceph-common.so.2). + * @param trace_type "osdtrace" or "radostrace". + * @param matched_version_out If non-null, set to the matched entry's + * version string on success (used by + * radostrace's squid-or-above gate so it can + * avoid a separate dpkg/rpm shell-out). + * @return true if a matching entry was found and imported. */ - bool import_from_embedded(const std::string& expected_version, const std::string& trace_type); + bool import_from_embedded( + const std::vector>& modules, + const std::string& trace_type, + std::string* matched_version_out = nullptr); static const char* dwarf_attr_string(unsigned int attrnum); static const char* dwarf_form_string(unsigned int form); diff --git a/src/osdtrace.cc b/src/osdtrace.cc index b8392b4..e3b7193 100644 --- a/src/osdtrace.cc +++ b/src/osdtrace.cc @@ -1369,10 +1369,13 @@ int main(int argc, char **argv) { } else { // When -j is used to export JSON, force live parsing so the output reflects // the installed binary (not a re-dump of the embedded data the header came - // from). Otherwise try embedded DWARF data first. - std::string version = get_package_version(osd_path); - if (!export_json && version != "unknown" && dwarfparser.import_from_embedded(version, "osdtrace")) { - clog << "Using embedded DWARF data for version: " << version << endl; + // from). Otherwise try embedded DWARF data first, keyed by the on-disk + // ELF build-id (arch-safe, snap-safe, custom-rebuild-safe). + std::string osd_buildid = get_elf_build_id(osd_path); + if (!export_json && !osd_buildid.empty() && + dwarfparser.import_from_embedded( + {{get_basename(osd_path), osd_buildid}}, "osdtrace")) { + // Detailed match info already logged inside import_from_embedded. } else { clog << "Start to parse dwarf info" << endl; dwarfparser.add_module(osd_path); diff --git a/src/radostrace.cc b/src/radostrace.cc index 3495722..128349d 100644 --- a/src/radostrace.cc +++ b/src/radostrace.cc @@ -527,6 +527,11 @@ int main(int argc, char **argv) { return 1; } + // Set by the embedded path on success; used later by the squid-version + // gate so it doesn't need a separate dpkg/rpm shell-out. + bool used_embedded = false; + std::string embedded_matched_version; + if (import_json) { clog << "Importing DWARF info from " << json_input_file << endl; @@ -552,10 +557,17 @@ int main(int argc, char **argv) { } else { // When -j is used to export JSON, force live parsing so the output reflects // the installed binary (not a re-dump of the embedded data the header came - // from). Otherwise try embedded DWARF data first. - std::string version = get_package_version(librados_path); - if (!export_json && version != "unknown" && dwarfparser.import_from_embedded(version, "radostrace")) { - clog << "Using embedded DWARF data for version: " << version << endl; + // from). Otherwise try embedded DWARF data first, keyed by the on-disk + // ELF build-id of each library. + std::vector> rados_mods = { + {get_basename(librbd_path), get_elf_build_id(librbd_path)}, + {get_basename(librados_path), get_elf_build_id(librados_path)}, + {get_basename(libceph_common_path), get_elf_build_id(libceph_common_path)}, + }; + if (!export_json && dwarfparser.import_from_embedded( + rados_mods, "radostrace", &embedded_matched_version)) { + used_embedded = true; + // Detailed match info already logged inside import_from_embedded. } else { clog << "Start to parse dwarf info" << endl; dwarfparser.add_module(librbd_path); @@ -564,10 +576,13 @@ int main(int argc, char **argv) { dwarfparser.parse(); } - // Export DWARF info to JSON if requested + // Export DWARF info to JSON if requested. Live-parse path only (we + // forced export_json off the embedded branch above), so resolve the + // version string from the package manager — the squid gate's path. if (export_json) { clog << "Exporting DWARF info to " << json_output_file << endl; + std::string version = get_package_version(librados_path); if (version != "unknown") { clog << "Detected package version: " << version << endl; } else { @@ -600,11 +615,17 @@ int main(int argc, char **argv) { * Values differ between Ceph versions due to struct layout changes. */ - // Determine Ceph version: from JSON file if importing, otherwise from package + // Determine Ceph version for the squid struct-offset gate, in priority order: + // 1. The "version" field of the JSON we just imported (-i path). + // 2. The matched embedded entry's version (build-id-keyed fast path). + // 3. dpkg/rpm package metadata for the live-parsed binary (live-parse path). std::string ceph_version; if (import_json) { ceph_version = get_version_from_json(json_input_file); clog << "Using version from JSON file: " << ceph_version << endl; + } else if (used_embedded && !embedded_matched_version.empty()) { + ceph_version = embedded_matched_version; + clog << "Using version from embedded match: " << ceph_version << endl; } else { ceph_version = get_package_version(librados_path); clog << "Using version from package: " << ceph_version << endl; From 88b97f6c3c9d21ea252ef8c61b0c8e001ca1bdd8 Mon Sep 17 00:00:00 2001 From: Dongdong Tao Date: Thu, 14 May 2026 17:41:47 +0900 Subject: [PATCH 07/13] tests: tolerate new top-level metadata + arch-suffixed reference filenames Three coupled test-side changes for the build-id-keyed JSON migration: 1. tests/compare_dwarf_json.py: replace the keys1 == keys2 top-level equality check with a positive predicate matching the C++ side's new "module entry = dict containing func2pc or func2vf" rule. Metadata keys (version, arch, and any future addition) are no longer flagged as diffs; differences are surfaced as informational notes the same way version differences already are. 2. tests/dwarf-compare.sh: glob the reference filename instead of hard-coding it, so reference JSONs that carry an optional arch suffix (osd-VERSION__dwarf.json) are picked up alongside the legacy arch-less naming. 3. tests/functional-test-microceph.sh: same glob fix for the runtime DWARF JSON discovery used by the --import-json path. All three changes are no-ops against existing JSONs and existing filename layouts; they only matter once the migration adds the metadata fields and arch-suffixed filenames begin appearing. --- tests/compare_dwarf_json.py | 39 ++++++++++++++++++------------ tests/dwarf-compare.sh | 13 ++++++++-- tests/functional-test-microceph.sh | 18 ++++++++------ 3 files changed, 45 insertions(+), 25 deletions(-) diff --git a/tests/compare_dwarf_json.py b/tests/compare_dwarf_json.py index 5bdb32c..bd0c2f5 100755 --- a/tests/compare_dwarf_json.py +++ b/tests/compare_dwarf_json.py @@ -240,14 +240,22 @@ def compare_dwarf_json(file1_path: str, file2_path: str, print(colored(f"Error: Invalid JSON in {file2_path}: {e}", Colors.RED)) return False - # Compare top-level keys - keys1 = set(data1.keys()) - keys2 = set(data2.keys()) + # Top-level metadata keys are informational; only module-content keys + # matter for offset-correctness. A module-content key has a dict value + # carrying func2pc and/or func2vf. + META_KEYS = {"version", "arch"} - if keys1 != keys2: - print(colored("Different top-level keys:", Colors.RED)) - only_in_1 = keys1 - keys2 - only_in_2 = keys2 - keys1 + def is_module_key(d, k): + v = d.get(k) + return isinstance(v, dict) and ("func2pc" in v or "func2vf" in v) + + mod_keys1 = {k for k in data1 if is_module_key(data1, k)} + mod_keys2 = {k for k in data2 if is_module_key(data2, k)} + + if mod_keys1 != mod_keys2: + print(colored("Different module-content keys:", Colors.RED)) + only_in_1 = mod_keys1 - mod_keys2 + only_in_2 = mod_keys2 - mod_keys1 if only_in_1: print(f" Only in {file1_path}: {only_in_1}") @@ -255,20 +263,21 @@ def compare_dwarf_json(file1_path: str, file2_path: str, print(f" Only in {file2_path}: {only_in_2}") return False - # Compare version (informational only, not a failure) - if "version" in data1 and "version" in data2: - if data1["version"] != data2["version"]: + # Surface metadata differences as informational only — they exist in + # the JSONs (arch, version) but never cause a comparison failure. + for meta in META_KEYS: + if meta in data1 and meta in data2 and data1[meta] != data2[meta]: if verbose: print(colored( - "Note: Version difference (informational only):", + f"Note: {meta} difference (informational only):", Colors.BLUE )) - print(f" {file1_path}: {data1['version']}") - print(f" {file2_path}: {data2['version']}") + print(f" {file1_path}: {data1[meta]}") + print(f" {file2_path}: {data2[meta]}") - # Compare each binary path + # Compare each module all_success = True - binary_paths = [k for k in keys1 if k != "version"] + binary_paths = list(mod_keys1) for binary_path in sorted(binary_paths): success, errors = compare_binary_data( diff --git a/tests/dwarf-compare.sh b/tests/dwarf-compare.sh index 1dbf074..c73c94b 100755 --- a/tests/dwarf-compare.sh +++ b/tests/dwarf-compare.sh @@ -102,11 +102,20 @@ fi # Get the ceph version for reference file lookup matching_ref_version=$(dpkg -l | awk '$2=="ceph-common" {print $3}') +# Reference filenames may carry an optional architecture suffix +# (e.g. osd-19.2.3-0ubuntu0.24.04.3_arm64_dwarf.json) when the same +# package version is checked in for more than one arch. Glob and pick +# the first match instead of hard-coding the filename. +find_ref() { + local dir="$1" prefix="$2" + ls "${dir}/${prefix}${matching_ref_version}"*_dwarf.json 2>/dev/null | head -1 +} + # Test osdtrace dwarf json generation echo "Testing osdtrace dwarf json generation..." osd_new_dwarf="generated-osd-dwarf.json" ./osdtrace -j $osd_new_dwarf -osd_ref_file="./files/ubuntu/osdtrace/osd-${matching_ref_version}_dwarf.json" +osd_ref_file=$(find_ref ./files/ubuntu/osdtrace osd-) ./tests/compare_dwarf_json.py $osd_ref_file $osd_new_dwarf echo "osdtrace dwarf json comparison passed!" @@ -114,7 +123,7 @@ echo "osdtrace dwarf json comparison passed!" echo "Testing radostrace dwarf json generation..." rados_new_dwarf="generated-rados-dwarf.json" ./radostrace -j $rados_new_dwarf -rados_ref_file="./files/ubuntu/radostrace/${matching_ref_version}_dwarf.json" +rados_ref_file=$(find_ref ./files/ubuntu/radostrace "") ./tests/compare_dwarf_json.py $rados_ref_file $rados_new_dwarf echo "radostrace dwarf json comparison passed!" diff --git a/tests/functional-test-microceph.sh b/tests/functional-test-microceph.sh index f7bc9a5..f73b794 100755 --- a/tests/functional-test-microceph.sh +++ b/tests/functional-test-microceph.sh @@ -93,12 +93,14 @@ fi info "Ceph version: $CEPH_VERSION" info "=== Step 3: Locate DWARF JSON files in repository ===" -# Look for matching DWARF files in the repository -OSD_DWARF="$PROJECT_ROOT/files/ubuntu/osdtrace/osd-${CEPH_VERSION}_dwarf.json" -RADOS_DWARF="$PROJECT_ROOT/files/ubuntu/radostrace/${CEPH_VERSION}_dwarf.json" - -if [ ! -f "$OSD_DWARF" ]; then - info "OSD DWARF file not found at $OSD_DWARF" +# Reference filenames may carry an optional architecture suffix +# (e.g. osd-19.2.3-0ubuntu0.24.04.3_arm64_dwarf.json) when multiple arches +# of the same package version are checked in. Glob and pick the first match. +OSD_DWARF=$(ls "$PROJECT_ROOT/files/ubuntu/osdtrace/osd-${CEPH_VERSION}"*_dwarf.json 2>/dev/null | head -1) +RADOS_DWARF=$(ls "$PROJECT_ROOT/files/ubuntu/radostrace/${CEPH_VERSION}"*_dwarf.json 2>/dev/null | head -1) + +if [ -z "$OSD_DWARF" ]; then + info "OSD DWARF file not found for version ${CEPH_VERSION}" info "Looking for any available OSD DWARF files..." OSD_DWARF=$(find "$PROJECT_ROOT/files/ubuntu/osdtrace/" -name "*_dwarf.json" | head -1) if [ -z "$OSD_DWARF" ]; then @@ -108,8 +110,8 @@ if [ ! -f "$OSD_DWARF" ]; then info "Using: $OSD_DWARF" fi -if [ ! -f "$RADOS_DWARF" ]; then - info "Rados DWARF file not found at $RADOS_DWARF" +if [ -z "$RADOS_DWARF" ]; then + info "Rados DWARF file not found for version ${CEPH_VERSION}" info "Looking for any available radostrace DWARF files..." RADOS_DWARF=$(find "$PROJECT_ROOT/files/ubuntu/radostrace/" -name "*_dwarf.json" | head -1) if [ -z "$RADOS_DWARF" ]; then From ecce65829f78875208646d4d96729613da3f96a6 Mon Sep 17 00:00:00 2001 From: Dongdong Tao Date: Thu, 14 May 2026 18:13:33 +0900 Subject: [PATCH 08/13] files: add build_id and arch metadata to existing reference JSONs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrates 37 of 49 reference DWARF JSONs from the legacy version-keyed schema to the new build-id-keyed schema by adding two fields: - top-level "arch": "amd64" (all checked-in JSONs are x86_64) - per-module "build_id": from the on-disk binary in the matching distribution package Generated by running tools/migrate_jsons_to_build_id.py, which fetches each .deb / .rpm and reads the GNU build-id via readelf -n. Also fixes the package mapping inside migrate_jsons_to_build_id.py: libceph-common.so.2 is shipped by librados2 (not libceph-common* / not ceph-base — neither package exists / contains it on Ubuntu). Verified by inspecting the contents of the 19.2.3-0ubuntu0.24.04.3 ceph-base, ceph-common, ceph-mon, librados2, librbd1, etc. .debs. 12 JSONs remain unmigrated and are documented in the script's output: 4 × CentOS Stream entries (centos-stream/{osdtrace,radostrace}/ {osd-,rados-}2:18.2.7-0.el9_dwarf.json, *2:19.2.3-0.el9_dwarf.json) — RPM mirror URL pattern in the script does not currently locate these. They keep working via --import-json. 7 × Ubuntu Cloud Archive entries (~cloud0 suffix on jammy) — the cloud archive uses a different pool layout than the cephadm/security PPAs the script knows about. 1 × Debian unstable entry (18.2.7+ds-1) — sourced from a different archive entirely. These twelve unmigrated JSONs will not match the build-id-keyed embedded fast path; they keep working via osdtrace -i / radostrace -i exactly as today. Generating their build-ids is a follow-up exercise (needs the cloud-archive pool path + a CentOS Stream mirror that still carries the rotated versions). --- .../ubuntu/osdtrace/osd-15.2.17-0ubuntu0.20.04.6_dwarf.json | 4 +++- .../ubuntu/osdtrace/osd-17.2.6-0ubuntu0.22.04.3_dwarf.json | 4 +++- .../ubuntu/osdtrace/osd-17.2.7-0ubuntu0.22.04.1_dwarf.json | 4 +++- .../ubuntu/osdtrace/osd-17.2.7-0ubuntu0.22.04.2_dwarf.json | 4 +++- .../ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.1_dwarf.json | 4 +++- .../osdtrace/osd-17.2.9-0ubuntu0.22.04.1~cloud0_dwarf.json | 4 +++- .../ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.2_dwarf.json | 4 +++- .../ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.3_dwarf.json | 4 +++- .../ubuntu/osdtrace/osd-19.2.0-0ubuntu0.24.04.2_dwarf.json | 4 +++- .../ubuntu/osdtrace/osd-19.2.1-0ubuntu0.24.04.2_dwarf.json | 4 +++- .../ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.1_dwarf.json | 4 +++- .../ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.2_dwarf.json | 4 +++- .../osdtrace/osd-19.2.3-0ubuntu0.24.04.2~cloud0_dwarf.json | 4 +++- .../ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.3_dwarf.json | 4 +++- files/ubuntu/osdtrace/osd-20.2.0-0ubuntu2_dwarf.json | 4 +++- files/ubuntu/radostrace/15.2.17-0ubuntu0.20.04.6_dwarf.json | 5 ++++- files/ubuntu/radostrace/17.2.0-0ubuntu0.22.04.1_dwarf.json | 6 +++++- files/ubuntu/radostrace/17.2.0-0ubuntu0.22.04.2_dwarf.json | 6 +++++- files/ubuntu/radostrace/17.2.5-0ubuntu0.22.04.1_dwarf.json | 6 +++++- files/ubuntu/radostrace/17.2.5-0ubuntu0.22.04.2_dwarf.json | 6 +++++- files/ubuntu/radostrace/17.2.5-0ubuntu0.22.04.3_dwarf.json | 6 +++++- files/ubuntu/radostrace/17.2.6-0ubuntu0.22.04.1_dwarf.json | 6 +++++- files/ubuntu/radostrace/17.2.6-0ubuntu0.22.04.2_dwarf.json | 6 +++++- files/ubuntu/radostrace/17.2.6-0ubuntu0.22.04.3_dwarf.json | 6 +++++- files/ubuntu/radostrace/17.2.7-0ubuntu0.22.04.1_dwarf.json | 6 +++++- files/ubuntu/radostrace/17.2.7-0ubuntu0.22.04.2_dwarf.json | 6 +++++- files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.1_dwarf.json | 6 +++++- .../radostrace/17.2.9-0ubuntu0.22.04.1~cloud0_dwarf.json | 6 +++++- files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.2_dwarf.json | 6 +++++- files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.3_dwarf.json | 6 +++++- files/ubuntu/radostrace/19.2.0-0ubuntu0.24.04.2_dwarf.json | 6 +++++- files/ubuntu/radostrace/19.2.1-0ubuntu0.24.04.2_dwarf.json | 6 +++++- files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.1_dwarf.json | 6 +++++- files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.2_dwarf.json | 6 +++++- .../radostrace/19.2.3-0ubuntu0.24.04.2~cloud0_dwarf.json | 6 +++++- files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.3_dwarf.json | 6 +++++- files/ubuntu/radostrace/20.2.0-0ubuntu2_dwarf.json | 4 +++- 37 files changed, 152 insertions(+), 37 deletions(-) diff --git a/files/ubuntu/osdtrace/osd-15.2.17-0ubuntu0.20.04.6_dwarf.json b/files/ubuntu/osdtrace/osd-15.2.17-0ubuntu0.20.04.6_dwarf.json index b630db8..dae75d2 100644 --- a/files/ubuntu/osdtrace/osd-15.2.17-0ubuntu0.20.04.6_dwarf.json +++ b/files/ubuntu/osdtrace/osd-15.2.17-0ubuntu0.20.04.6_dwarf.json @@ -1,6 +1,8 @@ { "version": "15.2.17-0ubuntu0.20.04.6", + "arch": "amd64", "ceph-osd": { + "build_id": "254fd8aa10290a29f04468e831951223a0a32ef1", "func2pc": { "BlueStore::_do_write": 11905456, "BlueStore::_txc_apply_kv": 11671824, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-17.2.6-0ubuntu0.22.04.3_dwarf.json b/files/ubuntu/osdtrace/osd-17.2.6-0ubuntu0.22.04.3_dwarf.json index 8d561e4..ecfc698 100644 --- a/files/ubuntu/osdtrace/osd-17.2.6-0ubuntu0.22.04.3_dwarf.json +++ b/files/ubuntu/osdtrace/osd-17.2.6-0ubuntu0.22.04.3_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.6-0ubuntu0.22.04.3", + "arch": "amd64", "ceph-osd": { + "build_id": "82b1bd65d889f7b6eb4223a95d81da84b1d2855a", "func2pc": { "BlueStore::_do_write": 12618640, "BlueStore::_txc_apply_kv": 12638624, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-17.2.7-0ubuntu0.22.04.1_dwarf.json b/files/ubuntu/osdtrace/osd-17.2.7-0ubuntu0.22.04.1_dwarf.json index 1400b51..a35879c 100644 --- a/files/ubuntu/osdtrace/osd-17.2.7-0ubuntu0.22.04.1_dwarf.json +++ b/files/ubuntu/osdtrace/osd-17.2.7-0ubuntu0.22.04.1_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.7-0ubuntu0.22.04.1", + "arch": "amd64", "ceph-osd": { + "build_id": "cda98ccdb608a670dd7e01f5c5f41bddee9ec2c7", "func2pc": { "BlueStore::_do_write": 12672656, "BlueStore::_txc_apply_kv": 12692640, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-17.2.7-0ubuntu0.22.04.2_dwarf.json b/files/ubuntu/osdtrace/osd-17.2.7-0ubuntu0.22.04.2_dwarf.json index 9e9003e..30fc71a 100644 --- a/files/ubuntu/osdtrace/osd-17.2.7-0ubuntu0.22.04.2_dwarf.json +++ b/files/ubuntu/osdtrace/osd-17.2.7-0ubuntu0.22.04.2_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.7-0ubuntu0.22.04.2", + "arch": "amd64", "ceph-osd": { + "build_id": "0d21298ec69fb32a3c78996a1ffcaf9e70ca8ba7", "func2pc": { "BlueStore::_do_write": 12672656, "BlueStore::_txc_apply_kv": 12692640, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.1_dwarf.json b/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.1_dwarf.json index 5ff8cdc..f0c5b33 100644 --- a/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.1_dwarf.json +++ b/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.1_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.9-0ubuntu0.22.04.1", + "arch": "amd64", "ceph-osd": { + "build_id": "a688608a8d0f7c30e67c81eaf6a476de7567fa71", "func2pc": { "BlueStore::_do_write": 12700304, "BlueStore::_txc_apply_kv": 12720160, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.1~cloud0_dwarf.json b/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.1~cloud0_dwarf.json index fc00843..9e5fd19 100644 --- a/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.1~cloud0_dwarf.json +++ b/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.1~cloud0_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.9-0ubuntu0.22.04.1~cloud0", + "arch": "amd64", "ceph-osd": { + "build_id": "a5ca92639c1e4333d03a37d192659655a3de3748", "func2pc": { "BlueStore::_do_write": 13608560, "BlueStore::_txc_apply_kv": 13449600, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.2_dwarf.json b/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.2_dwarf.json index f8173fb..edd5007 100644 --- a/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.2_dwarf.json +++ b/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.2_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.9-0ubuntu0.22.04.2", + "arch": "amd64", "ceph-osd": { + "build_id": "ddb878ac38ac981163fff4679ba5df948a274267", "func2pc": { "BlueStore::_do_write": 12700304, "BlueStore::_txc_apply_kv": 12720160, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.3_dwarf.json b/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.3_dwarf.json index 4ce0ba1..0342365 100644 --- a/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.3_dwarf.json +++ b/files/ubuntu/osdtrace/osd-17.2.9-0ubuntu0.22.04.3_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.9-0ubuntu0.22.04.3", + "arch": "amd64", "ceph-osd": { + "build_id": "28f0efa8527232967ff9b211f89f289e96ac9769", "func2pc": { "BlueStore::_do_write": 12700304, "BlueStore::_txc_apply_kv": 12720160, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-19.2.0-0ubuntu0.24.04.2_dwarf.json b/files/ubuntu/osdtrace/osd-19.2.0-0ubuntu0.24.04.2_dwarf.json index 8832508..9625676 100644 --- a/files/ubuntu/osdtrace/osd-19.2.0-0ubuntu0.24.04.2_dwarf.json +++ b/files/ubuntu/osdtrace/osd-19.2.0-0ubuntu0.24.04.2_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.0-0ubuntu0.24.04.2", + "arch": "amd64", "ceph-osd": { + "build_id": "6cac51923118fae61dd97b077cea3a0db3508da3", "func2pc": { "BlueStore::_do_write": 13814432, "BlueStore::_txc_apply_kv": 13528256, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-19.2.1-0ubuntu0.24.04.2_dwarf.json b/files/ubuntu/osdtrace/osd-19.2.1-0ubuntu0.24.04.2_dwarf.json index a960e1d..a633d33 100644 --- a/files/ubuntu/osdtrace/osd-19.2.1-0ubuntu0.24.04.2_dwarf.json +++ b/files/ubuntu/osdtrace/osd-19.2.1-0ubuntu0.24.04.2_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.1-0ubuntu0.24.04.2", + "arch": "amd64", "ceph-osd": { + "build_id": "1539cf3578d86760212fcaf1cba3feab688130eb", "func2pc": { "BlueStore::_do_write": 13889792, "BlueStore::_txc_apply_kv": 13629696, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.1_dwarf.json b/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.1_dwarf.json index 1977892..078dc87 100644 --- a/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.1_dwarf.json +++ b/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.1_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.3-0ubuntu0.24.04.1", + "arch": "amd64", "ceph-osd": { + "build_id": "8991bbab4afaa0dc7931bed26ec3332a963728da", "func2pc": { "BlueStore::_do_write": 13953952, "BlueStore::_txc_apply_kv": 13712192, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.2_dwarf.json b/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.2_dwarf.json index 5201281..7ea5e11 100644 --- a/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.2_dwarf.json +++ b/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.2_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.3-0ubuntu0.24.04.2", + "arch": "amd64", "ceph-osd": { + "build_id": "a7efdc6d17bfe217c38e7070b33c32f72dfc6441", "func2pc": { "BlueStore::_do_write": 13953952, "BlueStore::_txc_apply_kv": 13712192, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.2~cloud0_dwarf.json b/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.2~cloud0_dwarf.json index 98611e9..dddbf86 100644 --- a/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.2~cloud0_dwarf.json +++ b/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.2~cloud0_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.3-0ubuntu0.24.04.2~cloud0", + "arch": "amd64", "ceph-osd": { + "build_id": "5bd61ff1ed12112d364fc34933945dab2399c7ca", "func2pc": { "BlueStore::_do_write": 13452496, "BlueStore::_txc_apply_kv": 13131120, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.3_dwarf.json b/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.3_dwarf.json index e2ca688..3c64cb0 100644 --- a/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.3_dwarf.json +++ b/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.3_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.3-0ubuntu0.24.04.3", + "arch": "amd64", "ceph-osd": { + "build_id": "45df538869b8fda1a891a073b59326d635b26d5b", "func2pc": { "BlueStore::_do_write": 13953952, "BlueStore::_txc_apply_kv": 13712192, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-20.2.0-0ubuntu2_dwarf.json b/files/ubuntu/osdtrace/osd-20.2.0-0ubuntu2_dwarf.json index 72195a1..8d40f3d 100644 --- a/files/ubuntu/osdtrace/osd-20.2.0-0ubuntu2_dwarf.json +++ b/files/ubuntu/osdtrace/osd-20.2.0-0ubuntu2_dwarf.json @@ -1,6 +1,8 @@ { "version": "20.2.0-0ubuntu2", + "arch": "amd64", "ceph-osd": { + "build_id": "0e6c06a0aefaddbe0d5aea7b7d5b94f5befd3ce3", "func2pc": { "BlueStore::_do_write": 15514720, "BlueStore::_txc_apply_kv": 15095392, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/15.2.17-0ubuntu0.20.04.6_dwarf.json b/files/ubuntu/radostrace/15.2.17-0ubuntu0.20.04.6_dwarf.json index ae5e680..99c38fa 100644 --- a/files/ubuntu/radostrace/15.2.17-0ubuntu0.20.04.6_dwarf.json +++ b/files/ubuntu/radostrace/15.2.17-0ubuntu0.20.04.6_dwarf.json @@ -1,6 +1,8 @@ { "version": "15.2.17-0ubuntu0.20.04.6", + "arch": "amd64", "librados.so.2": { + "build_id": "4892287953c8a981e4000287d4f381e7ac599e4e", "func2pc": { "Objecter::_finish_op": 812976, "Objecter::_send_op": 735072 @@ -384,6 +386,7 @@ } }, "libceph-common.so.2": { + "build_id": "2e9588e73ed6d4089f8f08ec17e20ccd478a7e6e", "func2pc": { "Objecter::_finish_op": 8097360, "Objecter::_send_op": 8019456 @@ -766,4 +769,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/17.2.0-0ubuntu0.22.04.1_dwarf.json b/files/ubuntu/radostrace/17.2.0-0ubuntu0.22.04.1_dwarf.json index b246ede..8349708 100644 --- a/files/ubuntu/radostrace/17.2.0-0ubuntu0.22.04.1_dwarf.json +++ b/files/ubuntu/radostrace/17.2.0-0ubuntu0.22.04.1_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.0-0ubuntu0.22.04.1", + "arch": "amd64", "librados.so.2": { + "build_id": "68732f12aa9483799d7c5dfe7d905e8bff50099d", "func2pc": { "Objecter::_finish_op": 911328, "Objecter::_send_op": 856080 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "56a0177507e26cbceb1ad3a9651acee35c19fb01", "func2pc": { "Objecter::_finish_op": 6642512, "Objecter::_send_op": 6587264 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "a600f6536ef9708af4d55b9bd3a6d8f7f8893408", "func2pc": { "Objecter::_finish_op": 7968208, "Objecter::_send_op": 7912960 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/17.2.0-0ubuntu0.22.04.2_dwarf.json b/files/ubuntu/radostrace/17.2.0-0ubuntu0.22.04.2_dwarf.json index 2dfdd3e..32911d3 100644 --- a/files/ubuntu/radostrace/17.2.0-0ubuntu0.22.04.2_dwarf.json +++ b/files/ubuntu/radostrace/17.2.0-0ubuntu0.22.04.2_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.0-0ubuntu0.22.04.2", + "arch": "amd64", "librados.so.2": { + "build_id": "5a73375a8af561cde3e9cc1654f8836329a30943", "func2pc": { "Objecter::_finish_op": 911328, "Objecter::_send_op": 856080 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "b323f3ab71e82d6d32e4130345a4649f8d33a995", "func2pc": { "Objecter::_finish_op": 6642192, "Objecter::_send_op": 6586944 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "f3415ab4ff8752563dc9f450183b3e284e975591", "func2pc": { "Objecter::_finish_op": 7968208, "Objecter::_send_op": 7912960 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/17.2.5-0ubuntu0.22.04.1_dwarf.json b/files/ubuntu/radostrace/17.2.5-0ubuntu0.22.04.1_dwarf.json index 057376f..f88f8b6 100644 --- a/files/ubuntu/radostrace/17.2.5-0ubuntu0.22.04.1_dwarf.json +++ b/files/ubuntu/radostrace/17.2.5-0ubuntu0.22.04.1_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.5-0ubuntu0.22.04.1", + "arch": "amd64", "librados.so.2": { + "build_id": "a32e01d04b948842425ada3adcd60dd8779cd2dd", "func2pc": { "Objecter::_finish_op": 911184, "Objecter::_send_op": 855936 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "0b8681e7da80bc58c1dc67bd753c21e3d6ad60cb", "func2pc": { "Objecter::_finish_op": 6650432, "Objecter::_send_op": 6595184 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "2218872463fc65de6e1db349edd95b2de1cce190", "func2pc": { "Objecter::_finish_op": 7998080, "Objecter::_send_op": 7942832 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/17.2.5-0ubuntu0.22.04.2_dwarf.json b/files/ubuntu/radostrace/17.2.5-0ubuntu0.22.04.2_dwarf.json index 14cd9cd..bb8b041 100644 --- a/files/ubuntu/radostrace/17.2.5-0ubuntu0.22.04.2_dwarf.json +++ b/files/ubuntu/radostrace/17.2.5-0ubuntu0.22.04.2_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.5-0ubuntu0.22.04.2", + "arch": "amd64", "librados.so.2": { + "build_id": "ae9bbfe8e10aec3c51b671a3fee66c40f69eebbd", "func2pc": { "Objecter::_finish_op": 911184, "Objecter::_send_op": 855936 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "7b2cd4a351fd07be6ef5066fc260492aae5d72ea", "func2pc": { "Objecter::_finish_op": 6650432, "Objecter::_send_op": 6595184 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "7e15d123a3a7052331a7026274fd352a46067e12", "func2pc": { "Objecter::_finish_op": 7998080, "Objecter::_send_op": 7942832 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/17.2.5-0ubuntu0.22.04.3_dwarf.json b/files/ubuntu/radostrace/17.2.5-0ubuntu0.22.04.3_dwarf.json index e54e707..f7148e3 100644 --- a/files/ubuntu/radostrace/17.2.5-0ubuntu0.22.04.3_dwarf.json +++ b/files/ubuntu/radostrace/17.2.5-0ubuntu0.22.04.3_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.5-0ubuntu0.22.04.3", + "arch": "amd64", "librados.so.2": { + "build_id": "643dd2929e775d93334749097932857543cfa1fc", "func2pc": { "Objecter::_finish_op": 911184, "Objecter::_send_op": 855936 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "5c6e6bcb3ca7c8d546148fba8f051bede34cacfd", "func2pc": { "Objecter::_finish_op": 6650432, "Objecter::_send_op": 6595184 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "b33db934809bfa4cb77d099a19d75d0657621133", "func2pc": { "Objecter::_finish_op": 7998080, "Objecter::_send_op": 7942832 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/17.2.6-0ubuntu0.22.04.1_dwarf.json b/files/ubuntu/radostrace/17.2.6-0ubuntu0.22.04.1_dwarf.json index da4439d..85ce077 100644 --- a/files/ubuntu/radostrace/17.2.6-0ubuntu0.22.04.1_dwarf.json +++ b/files/ubuntu/radostrace/17.2.6-0ubuntu0.22.04.1_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.6-0ubuntu0.22.04.1", + "arch": "amd64", "librados.so.2": { + "build_id": "c954a96ff5fe2b64e6ded8187f203c799a11768f", "func2pc": { "Objecter::_finish_op": 911264, "Objecter::_send_op": 856016 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "ce5c5fbf27f371387f2566be0759affe2d47ec3e", "func2pc": { "Objecter::_finish_op": 6657552, "Objecter::_send_op": 6602304 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "f48b8b47c0ddcb39351f8de5cb660df3eadf0713", "func2pc": { "Objecter::_finish_op": 8015824, "Objecter::_send_op": 7960576 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/17.2.6-0ubuntu0.22.04.2_dwarf.json b/files/ubuntu/radostrace/17.2.6-0ubuntu0.22.04.2_dwarf.json index 1a36015..807436e 100644 --- a/files/ubuntu/radostrace/17.2.6-0ubuntu0.22.04.2_dwarf.json +++ b/files/ubuntu/radostrace/17.2.6-0ubuntu0.22.04.2_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.6-0ubuntu0.22.04.2", + "arch": "amd64", "librados.so.2": { + "build_id": "923e5e5d13554c263fa615bcc4e16c2dc039b1ef", "func2pc": { "Objecter::_finish_op": 911152, "Objecter::_send_op": 855888 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "ec9806c8c9149360eb9a51357791c3d982de8dc9", "func2pc": { "Objecter::_finish_op": 6658672, "Objecter::_send_op": 6603408 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "29532fd24051236703d09cee5217d7b42e5ce2ab", "func2pc": { "Objecter::_finish_op": 8022128, "Objecter::_send_op": 7966864 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/17.2.6-0ubuntu0.22.04.3_dwarf.json b/files/ubuntu/radostrace/17.2.6-0ubuntu0.22.04.3_dwarf.json index 1c0625e..da93fd4 100644 --- a/files/ubuntu/radostrace/17.2.6-0ubuntu0.22.04.3_dwarf.json +++ b/files/ubuntu/radostrace/17.2.6-0ubuntu0.22.04.3_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.6-0ubuntu0.22.04.3", + "arch": "amd64", "librados.so.2": { + "build_id": "21ef9b94e2f96e6f5c767a35e1fc6a74a9fb5c73", "func2pc": { "Objecter::_finish_op": 911152, "Objecter::_send_op": 855888 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "6005fbe9f0c62cc81fcf79643d9e5875f6eb967c", "func2pc": { "Objecter::_finish_op": 6658672, "Objecter::_send_op": 6603408 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "d25ebfac79b7a9395904bf93bb8dd04df31d8721", "func2pc": { "Objecter::_finish_op": 8022128, "Objecter::_send_op": 7966864 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/17.2.7-0ubuntu0.22.04.1_dwarf.json b/files/ubuntu/radostrace/17.2.7-0ubuntu0.22.04.1_dwarf.json index 21f71c3..78b483e 100644 --- a/files/ubuntu/radostrace/17.2.7-0ubuntu0.22.04.1_dwarf.json +++ b/files/ubuntu/radostrace/17.2.7-0ubuntu0.22.04.1_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.7-0ubuntu0.22.04.1", + "arch": "amd64", "librados.so.2": { + "build_id": "cafadffdf5eb235b5d18c6c05f48a3c378ee4b69", "func2pc": { "Objecter::_finish_op": 911504, "Objecter::_send_op": 856240 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "868313943d1043b82b0b2e5cc8c60874a32cc98b", "func2pc": { "Objecter::_finish_op": 6648928, "Objecter::_send_op": 6593664 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "d8d28791be0c47901ede5933d2b05a9d3f0d4683", "func2pc": { "Objecter::_finish_op": 8029888, "Objecter::_send_op": 7974624 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/17.2.7-0ubuntu0.22.04.2_dwarf.json b/files/ubuntu/radostrace/17.2.7-0ubuntu0.22.04.2_dwarf.json index 3a630a6..c570e16 100644 --- a/files/ubuntu/radostrace/17.2.7-0ubuntu0.22.04.2_dwarf.json +++ b/files/ubuntu/radostrace/17.2.7-0ubuntu0.22.04.2_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.7-0ubuntu0.22.04.2", + "arch": "amd64", "librados.so.2": { + "build_id": "36b8f62bbf6399f81a7182b8b086bc440e62cf0e", "func2pc": { "Objecter::_finish_op": 911504, "Objecter::_send_op": 856240 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "19b1be8cdc9f193a53da13e3e8a69f22dd272bc4", "func2pc": { "Objecter::_finish_op": 6648928, "Objecter::_send_op": 6593664 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "8e95b1bfe63e7389cb79c6004d83cc09740a8db6", "func2pc": { "Objecter::_finish_op": 8029888, "Objecter::_send_op": 7974624 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.1_dwarf.json b/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.1_dwarf.json index 68450a1..092bb71 100644 --- a/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.1_dwarf.json +++ b/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.1_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.9-0ubuntu0.22.04.1", + "arch": "amd64", "librados.so.2": { + "build_id": "9eb36079123e5d0c82aa570ecfb39509e00630ff", "func2pc": { "Objecter::_finish_op": 912400, "Objecter::_send_op": 857136 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "d4f4b4a472dd702d803a2e52df299e9759113395", "func2pc": { "Objecter::_finish_op": 6656176, "Objecter::_send_op": 6600912 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "377e998560a9285eccfa13858e549388418a5262", "func2pc": { "Objecter::_finish_op": 8068480, "Objecter::_send_op": 8013216 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.1~cloud0_dwarf.json b/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.1~cloud0_dwarf.json index efd8f34..3ee31c9 100644 --- a/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.1~cloud0_dwarf.json +++ b/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.1~cloud0_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.9-0ubuntu0.22.04.1~cloud0", + "arch": "amd64", "librados.so.2": { + "build_id": "f2dbc3fd0e66e74c4c5582daaad7345f855cc082", "func2pc": { "Objecter::_finish_op": 945200, "Objecter::_send_op": 885008 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "c97db865428223b868711d89be1546d6ac65b55c", "func2pc": { "Objecter::_finish_op": 7074592, "Objecter::_send_op": 7014400 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "31393363d4adfc6ba4c8e4e58ba7a84792193077", "func2pc": { "Objecter::_finish_op": 8508416, "Objecter::_send_op": 8448224 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.2_dwarf.json b/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.2_dwarf.json index b0cafba..135551d 100644 --- a/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.2_dwarf.json +++ b/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.2_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.9-0ubuntu0.22.04.2", + "arch": "amd64", "libceph-common.so.2": { + "build_id": "57f970773446c1df4a4565308d26a790189cb0da", "func2pc": { "Objecter::_finish_op": 8068480, "Objecter::_send_op": 8013216 @@ -384,6 +386,7 @@ } }, "librados.so.2": { + "build_id": "a463bb64f70ebb6a40d2705472181460d8a88368", "func2pc": { "Objecter::_finish_op": 912400, "Objecter::_send_op": 857136 @@ -767,6 +770,7 @@ } }, "librbd.so.1": { + "build_id": "d547af0b0399ed47a5ca02ff405833e43a65e4f7", "func2pc": { "Objecter::_finish_op": 6656176, "Objecter::_send_op": 6600912 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.3_dwarf.json b/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.3_dwarf.json index 4c89f32..0ce1ff3 100644 --- a/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.3_dwarf.json +++ b/files/ubuntu/radostrace/17.2.9-0ubuntu0.22.04.3_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.9-0ubuntu0.22.04.3", + "arch": "amd64", "libceph-common.so.2": { + "build_id": "a43ecd6fc4c2c0134a59877e713982fd4a12cbb0", "func2pc": { "Objecter::_finish_op": 8068480, "Objecter::_send_op": 8013216 @@ -384,6 +386,7 @@ } }, "librados.so.2": { + "build_id": "f1398972d932897a10e0bd7ee32a1f66d9fb604c", "func2pc": { "Objecter::_finish_op": 912400, "Objecter::_send_op": 857136 @@ -767,6 +770,7 @@ } }, "librbd.so.1": { + "build_id": "4b6bb7f814905c0f47c9bdc5ff0a80d956df1d3b", "func2pc": { "Objecter::_finish_op": 6656176, "Objecter::_send_op": 6600912 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/19.2.0-0ubuntu0.24.04.2_dwarf.json b/files/ubuntu/radostrace/19.2.0-0ubuntu0.24.04.2_dwarf.json index d52fb40..ad696a1 100644 --- a/files/ubuntu/radostrace/19.2.0-0ubuntu0.24.04.2_dwarf.json +++ b/files/ubuntu/radostrace/19.2.0-0ubuntu0.24.04.2_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.0-0ubuntu0.24.04.2", + "arch": "amd64", "librados.so.2": { + "build_id": "91f01ef79488aa7d971d460d220a7fc31fec6645", "func2pc": { "Objecter::_finish_op": 1012832, "Objecter::_send_op": 955376 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "1a30a0bfe2760961020d56c7c9a60e3d6ee6a7e3", "func2pc": { "Objecter::_finish_op": 6869280, "Objecter::_send_op": 6811824 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "611e483f63289443c1d5f51f8af125b593723ea6", "func2pc": { "Objecter::_finish_op": 8908560, "Objecter::_send_op": 8851104 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/19.2.1-0ubuntu0.24.04.2_dwarf.json b/files/ubuntu/radostrace/19.2.1-0ubuntu0.24.04.2_dwarf.json index 8c0eaa5..7d4becd 100644 --- a/files/ubuntu/radostrace/19.2.1-0ubuntu0.24.04.2_dwarf.json +++ b/files/ubuntu/radostrace/19.2.1-0ubuntu0.24.04.2_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.1-0ubuntu0.24.04.2", + "arch": "amd64", "librados.so.2": { + "build_id": "94838690d797823defbfa137510ce9b4d3772551", "func2pc": { "Objecter::_finish_op": 1009184, "Objecter::_send_op": 951344 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "8f660675cd4b45b1f7015b6f2b72e8764b6b70b4", "func2pc": { "Objecter::_finish_op": 7431936, "Objecter::_send_op": 7374096 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "9c132c525a73ef4cab19b088f8e7723ac6171281", "func2pc": { "Objecter::_finish_op": 9105376, "Objecter::_send_op": 9047536 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.1_dwarf.json b/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.1_dwarf.json index 719187e..256d130 100644 --- a/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.1_dwarf.json +++ b/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.1_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.3-0ubuntu0.24.04.1", + "arch": "amd64", "libceph-common.so.2": { + "build_id": "6add8450230eaccfcfcd85f103f77cfb3b06cff7", "func2pc": { "Objecter::_finish_op": 8977024, "Objecter::_send_op": 8919424 @@ -384,6 +386,7 @@ } }, "librados.so.2": { + "build_id": "7a09e56c25e53664261df4bc6815ce24d672e646", "func2pc": { "Objecter::_finish_op": 1149312, "Objecter::_send_op": 1091712 @@ -767,6 +770,7 @@ } }, "librbd.so.1": { + "build_id": "2a72ed7b3b4d374c5c6a7443a2339928631952e0", "func2pc": { "Objecter::_finish_op": 7118656, "Objecter::_send_op": 7061056 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.2_dwarf.json b/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.2_dwarf.json index a81565d..6ebca03 100644 --- a/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.2_dwarf.json +++ b/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.2_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.3-0ubuntu0.24.04.2", + "arch": "amd64", "libceph-common.so.2": { + "build_id": "8e05084d6ecbbebdcd583bb8795bd9ddf9c616c6", "func2pc": { "Objecter::_finish_op": 8977024, "Objecter::_send_op": 8919424 @@ -384,6 +386,7 @@ } }, "librados.so.2": { + "build_id": "2b2295354fbf99334da15d29b221a09f4e8bcba5", "func2pc": { "Objecter::_finish_op": 1149312, "Objecter::_send_op": 1091712 @@ -767,6 +770,7 @@ } }, "librbd.so.1": { + "build_id": "a9715e6a4aa511f5a1bd1d55799a311e1b790855", "func2pc": { "Objecter::_finish_op": 7118656, "Objecter::_send_op": 7061056 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.2~cloud0_dwarf.json b/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.2~cloud0_dwarf.json index eaf119c..7b03027 100644 --- a/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.2~cloud0_dwarf.json +++ b/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.2~cloud0_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.3-0ubuntu0.24.04.2~cloud0", + "arch": "amd64", "libceph-common.so.2": { + "build_id": "99f34aec2b1169ecb0267a773842bf77cbb95484", "func2pc": { "Objecter::_finish_op": 8738144, "Objecter::_send_op": 8678368 @@ -384,6 +386,7 @@ } }, "librados.so.2": { + "build_id": "fcd825f262d3644f10281be3dc3f1ef092a1cee7", "func2pc": { "Objecter::_finish_op": 1087760, "Objecter::_send_op": 1027984 @@ -767,6 +770,7 @@ } }, "librbd.so.1": { + "build_id": "c7a5be6db83749187542a7ae6a14ccbda1a4155c", "func2pc": { "Objecter::_finish_op": 7416048, "Objecter::_send_op": 7356272 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.3_dwarf.json b/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.3_dwarf.json index 5250682..fa11e38 100644 --- a/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.3_dwarf.json +++ b/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.3_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.3-0ubuntu0.24.04.3", + "arch": "amd64", "libceph-common.so.2": { + "build_id": "32ad4188ce47ad37a07b7816aaadc6e76f428e12", "func2pc": { "Objecter::_finish_op": 8977024, "Objecter::_send_op": 8919424 @@ -384,6 +386,7 @@ } }, "librados.so.2": { + "build_id": "5cd6979f3a7bea8c677e48e48f6f657e7d8ded1c", "func2pc": { "Objecter::_finish_op": 1149312, "Objecter::_send_op": 1091712 @@ -767,6 +770,7 @@ } }, "librbd.so.1": { + "build_id": "dd80fe7d53cc973642db071ac6ecce8504de3a97", "func2pc": { "Objecter::_finish_op": 7118656, "Objecter::_send_op": 7061056 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/20.2.0-0ubuntu2_dwarf.json b/files/ubuntu/radostrace/20.2.0-0ubuntu2_dwarf.json index 08a5dba..28d87c7 100644 --- a/files/ubuntu/radostrace/20.2.0-0ubuntu2_dwarf.json +++ b/files/ubuntu/radostrace/20.2.0-0ubuntu2_dwarf.json @@ -1,6 +1,8 @@ { "version": "20.2.0-0ubuntu2", + "arch": "amd64", "libceph-common.so.2": { + "build_id": "0f51328e7a9b17cf038a8acfb9ef4e06fa7bbb0c", "func2pc": { "Objecter::_finish_op": 9783056, "Objecter::_send_op": 9720816 @@ -383,4 +385,4 @@ } } } -} \ No newline at end of file +} From dba9ed69e3d3fa5a99175caeca409133947a8ea9 Mon Sep 17 00:00:00 2001 From: Dongdong Tao Date: Thu, 14 May 2026 23:40:31 +0900 Subject: [PATCH 09/13] tools+files: cover cloud-archive / Debian / CentOS in the migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three small additions to migrate_jsons_to_build_id.py close the remaining 12-of-49 gap by adding archive-specific URL discovery and a pure-Python RPM extractor: 1. Ubuntu Cloud Archive (~cloudN versions). These don't appear in ubuntu/+source/ on Launchpad — they're published in PPAs under launchpad.net/~ubuntu-cloud-archive (caracal-staging, yoga-staging, etc.). Probe a candidate PPA list for each ~cloudN version's ceph_.dsc until one matches, then fetch the .deb from the same PPA's +files endpoint. 2. Debian unstable (e.g. 18.2.7+ds-1). Pull from snapshot.debian.org via its JSON binfiles API: look up the binary by name+version, read the SHA-1 hash, fetch /file/. 3. CentOS Stream RPMs (2:VER-0.el9). Add download.ceph.com/rpm-/ (upstream version-pinned archive) ahead of the mirror.stream.centos.org paths in the candidate list. Older versions long rotated out of CentOS Stream's distro pools are still kept here by the Ceph project itself. To avoid forcing rpm2cpio onto every contributor's machine, also add _extract_rpm_pure_python(): a stdlib-only fallback that locates the xz magic inside the RPM (skipping lead+signature+header), decompresses with lzma, and walks the newc cpio payload writing regular files into dest_dir. rpm2cpio + cpio are still tried first when available. End-to-end result: 49 of 49 reference JSONs now carry "arch" and per-module "build_id" fields. The build-id-keyed embedded fast path now covers every supported Ceph version cephtrace ships data for. --- files/centos-stream/osdtrace/osd-2:18.2.7-0.el9_dwarf.json | 4 +++- files/centos-stream/osdtrace/osd-2:19.2.3-0.el9_dwarf.json | 4 +++- .../radostrace/rados-2:18.2.7-0.el9_dwarf.json | 6 +++++- .../radostrace/rados-2:19.2.3-0.el9_dwarf.json | 6 +++++- files/debian/osdtrace/osd-18.2.7+ds-1_dwarf.json | 4 +++- files/debian/radostrace/18.2.7+ds-1_dwarf.json | 6 +++++- .../osdtrace/osd-17.2.7-0ubuntu0.22.04.1~cloud0_dwarf.json | 4 +++- .../osdtrace/osd-19.2.1-0ubuntu0.24.04.2~cloud0_dwarf.json | 4 +++- .../osdtrace/osd-19.2.3-0ubuntu0.24.04.1~cloud0_dwarf.json | 4 +++- .../radostrace/17.2.7-0ubuntu0.22.04.1~cloud0_dwarf.json | 6 +++++- .../radostrace/19.2.0-0ubuntu0.24.04.2~cloud0_dwarf.json | 6 +++++- .../radostrace/19.2.3-0ubuntu0.24.04.1~cloud0_dwarf.json | 6 +++++- 12 files changed, 48 insertions(+), 12 deletions(-) diff --git a/files/centos-stream/osdtrace/osd-2:18.2.7-0.el9_dwarf.json b/files/centos-stream/osdtrace/osd-2:18.2.7-0.el9_dwarf.json index 4ced362..cd1409d 100644 --- a/files/centos-stream/osdtrace/osd-2:18.2.7-0.el9_dwarf.json +++ b/files/centos-stream/osdtrace/osd-2:18.2.7-0.el9_dwarf.json @@ -1,6 +1,8 @@ { "version": "2:18.2.7-0.el9", + "arch": "amd64", "ceph-osd": { + "build_id": "55d2fa99b99cb563a50089732bf2f92e681d64c1", "func2pc": { "BlueStore::_do_write": 10013648, "BlueStore::_txc_apply_kv": 9908624, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/centos-stream/osdtrace/osd-2:19.2.3-0.el9_dwarf.json b/files/centos-stream/osdtrace/osd-2:19.2.3-0.el9_dwarf.json index f6ac0e5..a350964 100644 --- a/files/centos-stream/osdtrace/osd-2:19.2.3-0.el9_dwarf.json +++ b/files/centos-stream/osdtrace/osd-2:19.2.3-0.el9_dwarf.json @@ -1,6 +1,8 @@ { "version": "2:19.2.3-0.el9", + "arch": "amd64", "ceph-osd": { + "build_id": "39ec76a70203385f8c9fbf812b95f32821290c8b", "func2pc": { "BlueStore::_do_write": 10466544, "BlueStore::_txc_apply_kv": 10347168, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/centos-stream/radostrace/rados-2:18.2.7-0.el9_dwarf.json b/files/centos-stream/radostrace/rados-2:18.2.7-0.el9_dwarf.json index 52d3710..f3e2242 100644 --- a/files/centos-stream/radostrace/rados-2:18.2.7-0.el9_dwarf.json +++ b/files/centos-stream/radostrace/rados-2:18.2.7-0.el9_dwarf.json @@ -1,6 +1,8 @@ { "version": "2:18.2.7-0.el9", + "arch": "amd64", "libceph-common.so.2": { + "build_id": "45c9fc9d45c392ed96f6ed2283fc4af3112c988f", "func2pc": { "Objecter::_finish_op": 5875648, "Objecter::_send_op": 5911280 @@ -384,6 +386,7 @@ } }, "librados.so.2": { + "build_id": "1cc1de0162303fe049602ddeb7dff08bd5b3be95", "func2pc": { "Objecter::_finish_op": 949904, "Objecter::_send_op": 953376 @@ -767,6 +770,7 @@ } }, "librbd.so.1": { + "build_id": "d811a761bad04cf251df2eb54e9f90549e8287da", "func2pc": { "Objecter::_finish_op": 4932624 }, @@ -836,4 +840,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/centos-stream/radostrace/rados-2:19.2.3-0.el9_dwarf.json b/files/centos-stream/radostrace/rados-2:19.2.3-0.el9_dwarf.json index d3db468..c9645a0 100644 --- a/files/centos-stream/radostrace/rados-2:19.2.3-0.el9_dwarf.json +++ b/files/centos-stream/radostrace/rados-2:19.2.3-0.el9_dwarf.json @@ -1,6 +1,8 @@ { "version": "2:19.2.3-0.el9", + "arch": "amd64", "libceph-common.so.2": { + "build_id": "5f1ea54f7dd4fce58abc75258c0df12e319301b4", "func2pc": { "Objecter::_finish_op": 6154944, "Objecter::_send_op": 6174752 @@ -384,6 +386,7 @@ } }, "librados.so.2": { + "build_id": "ede96d38d9db3413a5776505852fe1ad68ef19a1", "func2pc": { "Objecter::_finish_op": 965808, "Objecter::_send_op": 975616 @@ -767,6 +770,7 @@ } }, "librbd.so.1": { + "build_id": "7a16ab05e3ae5c34fa4f528cb222826708a02cc0", "func2pc": { "Objecter::_finish_op": 5201856 }, @@ -836,4 +840,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/debian/osdtrace/osd-18.2.7+ds-1_dwarf.json b/files/debian/osdtrace/osd-18.2.7+ds-1_dwarf.json index 20c2880..861f965 100644 --- a/files/debian/osdtrace/osd-18.2.7+ds-1_dwarf.json +++ b/files/debian/osdtrace/osd-18.2.7+ds-1_dwarf.json @@ -1,6 +1,8 @@ { "version": "18.2.7+ds-1", + "arch": "amd64", "ceph-osd": { + "build_id": "43240de334d28cf53de108f7d44110a81bd6ee79", "func2pc": { "BlueStore::_do_write": 13671680, "BlueStore::_txc_apply_kv": 13302208, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/debian/radostrace/18.2.7+ds-1_dwarf.json b/files/debian/radostrace/18.2.7+ds-1_dwarf.json index 10227c5..a922d81 100644 --- a/files/debian/radostrace/18.2.7+ds-1_dwarf.json +++ b/files/debian/radostrace/18.2.7+ds-1_dwarf.json @@ -1,6 +1,8 @@ { "version": "18.2.7+ds-1", + "arch": "amd64", "libceph-common.so.2": { + "build_id": "3d5071d7aa3ba5906909b5af9c17916d49f463d9", "func2pc": { "Objecter::_finish_op": 8731584, "Objecter::_send_op": 8675392 @@ -384,6 +386,7 @@ } }, "librados.so.2": { + "build_id": "db58d5e5bd1ed353110ae4b19ba270c188a27e8b", "func2pc": { "Objecter::_finish_op": 1005696, "Objecter::_send_op": 949504 @@ -767,6 +770,7 @@ } }, "librbd.so.1": { + "build_id": "e5806305275cda8edc4e898b9b3cf9c1170a34c0", "func2pc": { "Objecter::_finish_op": 7208192, "Objecter::_send_op": 7152000 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-17.2.7-0ubuntu0.22.04.1~cloud0_dwarf.json b/files/ubuntu/osdtrace/osd-17.2.7-0ubuntu0.22.04.1~cloud0_dwarf.json index 0dbebf8..6cf6f76 100644 --- a/files/ubuntu/osdtrace/osd-17.2.7-0ubuntu0.22.04.1~cloud0_dwarf.json +++ b/files/ubuntu/osdtrace/osd-17.2.7-0ubuntu0.22.04.1~cloud0_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.7-0ubuntu0.22.04.1~cloud0", + "arch": "amd64", "ceph-osd": { + "build_id": "e427742f98a87fcfe343d5aaba10d9b07ce4c32f", "func2pc": { "BlueStore::_do_write": 13642848, "BlueStore::_txc_apply_kv": 13396272, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-19.2.1-0ubuntu0.24.04.2~cloud0_dwarf.json b/files/ubuntu/osdtrace/osd-19.2.1-0ubuntu0.24.04.2~cloud0_dwarf.json index d47b09b..96ab1a6 100644 --- a/files/ubuntu/osdtrace/osd-19.2.1-0ubuntu0.24.04.2~cloud0_dwarf.json +++ b/files/ubuntu/osdtrace/osd-19.2.1-0ubuntu0.24.04.2~cloud0_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.1-0ubuntu0.24.04.2~cloud0", + "arch": "amd64", "ceph-osd": { + "build_id": "0d53e1cd97eca4d6b469ef503c3ab3faf0d57a5f", "func2pc": { "BlueStore::_do_write": 13321184, "BlueStore::_txc_apply_kv": 13340736, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.1~cloud0_dwarf.json b/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.1~cloud0_dwarf.json index 9c5e8b1..494c01b 100644 --- a/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.1~cloud0_dwarf.json +++ b/files/ubuntu/osdtrace/osd-19.2.3-0ubuntu0.24.04.1~cloud0_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.3-0ubuntu0.24.04.1~cloud0", + "arch": "amd64", "ceph-osd": { + "build_id": "e5aa09c2c41c7a6fe89fd00d00d6377ed668e04e", "func2pc": { "BlueStore::_do_write": 13452496, "BlueStore::_txc_apply_kv": 13131120, @@ -1333,4 +1335,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/17.2.7-0ubuntu0.22.04.1~cloud0_dwarf.json b/files/ubuntu/radostrace/17.2.7-0ubuntu0.22.04.1~cloud0_dwarf.json index 1e10e81..45b5c1d 100644 --- a/files/ubuntu/radostrace/17.2.7-0ubuntu0.22.04.1~cloud0_dwarf.json +++ b/files/ubuntu/radostrace/17.2.7-0ubuntu0.22.04.1~cloud0_dwarf.json @@ -1,6 +1,8 @@ { "version": "17.2.7-0ubuntu0.22.04.1~cloud0", + "arch": "amd64", "librados.so.2": { + "build_id": "fc2b885a83d389143d21b0e436d1039c6169d8e0", "func2pc": { "Objecter::_finish_op": 946544, "Objecter::_send_op": 886112 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "62f088942b7767eabf3f7a211d55e1570a3b7bdd", "func2pc": { "Objecter::_finish_op": 7051904, "Objecter::_send_op": 6991472 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "60540ba00e9c885fe1cbc20fc66a6bcbcef6e7dc", "func2pc": { "Objecter::_finish_op": 8471872, "Objecter::_send_op": 8411440 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/19.2.0-0ubuntu0.24.04.2~cloud0_dwarf.json b/files/ubuntu/radostrace/19.2.0-0ubuntu0.24.04.2~cloud0_dwarf.json index 26ca94b..609025f 100644 --- a/files/ubuntu/radostrace/19.2.0-0ubuntu0.24.04.2~cloud0_dwarf.json +++ b/files/ubuntu/radostrace/19.2.0-0ubuntu0.24.04.2~cloud0_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.0-0ubuntu0.24.04.2~cloud0", + "arch": "amd64", "librados.so.2": { + "build_id": "b88ed685ad283f9259df920fa969bdc266e5cf3f", "func2pc": { "Objecter::_finish_op": 960560, "Objecter::_send_op": 901104 @@ -384,6 +386,7 @@ } }, "librbd.so.1": { + "build_id": "a3f1e9db89cee48c44ae9d23434a7da70aea7317", "func2pc": { "Objecter::_finish_op": 7129760, "Objecter::_send_op": 7070304 @@ -767,6 +770,7 @@ } }, "libceph-common.so.2": { + "build_id": "f5b2886579b5c465471b9b71d4e8ecf2f5147562", "func2pc": { "Objecter::_finish_op": 8655344, "Objecter::_send_op": 8595888 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} diff --git a/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.1~cloud0_dwarf.json b/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.1~cloud0_dwarf.json index 7a9eeeb..d2083e0 100644 --- a/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.1~cloud0_dwarf.json +++ b/files/ubuntu/radostrace/19.2.3-0ubuntu0.24.04.1~cloud0_dwarf.json @@ -1,6 +1,8 @@ { "version": "19.2.3-0ubuntu0.24.04.1~cloud0", + "arch": "amd64", "libceph-common.so.2": { + "build_id": "1b3c93f1a202ebdbaa723ccd8df0ceaaffeea83d", "func2pc": { "Objecter::_finish_op": 8738144, "Objecter::_send_op": 8678368 @@ -384,6 +386,7 @@ } }, "librados.so.2": { + "build_id": "3fdbb3d7688d1fc7cee7e3424de889a907bb12cc", "func2pc": { "Objecter::_finish_op": 1087760, "Objecter::_send_op": 1027984 @@ -767,6 +770,7 @@ } }, "librbd.so.1": { + "build_id": "36664c484f5b45508525c52badfe5fbbd9b2ca29", "func2pc": { "Objecter::_finish_op": 7416048, "Objecter::_send_op": 7356272 @@ -1149,4 +1153,4 @@ } } } -} \ No newline at end of file +} From 3d61711c98136e73fffdc584b6825848d641c0bd Mon Sep 17 00:00:00 2001 From: Dongdong Tao Date: Fri, 15 May 2026 00:18:09 +0900 Subject: [PATCH 10/13] Fix CI failures: log marker prefix + tools/ lint cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two unrelated regressions surfaced by the first CI run on PR #98: 1. tests/functional-test-embedded-dwarf.sh greps for the string "Using embedded DWARF data" as the embedded-mode marker (assertions 8.1 and 9.1). My new import_from_embedded() log line said "Found embedded DWARF data (...)" — neither marker was present in the log, so the test failed even when the embedded path actually matched the target binary's build-id. Restore the "Using embedded DWARF data" prefix; the new per-module build-id breakdown still follows on subsequent lines. 2. flake8 in tools/ reported one F401 (unused 'os' import), two E231 (missing whitespace after commas), and a handful of E501 (lines exceeding the 79-char default). Trivial mechanical fixes — shorten URL strings via factored-out base-URL variables, drop the unused import, split a multi-line list literal. No behavioural change beyond the log-prefix tweak. Verified locally: make osdtrace radostrace kfstrace builds clean; flake8-equivalent 80-col scan reports no remaining violations in tools/. --- src/dwarf_parser.cc | 8 +++++--- tools/generate_embedded_dwarf.py | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/dwarf_parser.cc b/src/dwarf_parser.cc index ea8b6c2..272c131 100644 --- a/src/dwarf_parser.cc +++ b/src/dwarf_parser.cc @@ -1060,9 +1060,11 @@ bool DwarfParser::import_from_embedded( return false; } - // Log every matched module's (basename, build-id) so failures further - // downstream can be correlated with the exact embedded entry used. - std::clog << "Found embedded DWARF data (version " + // Marker line preserves the "Using embedded DWARF data" prefix that + // tests (and downstream log consumers) grep for; the detailed + // per-module build-ids follow so a failing trace can be correlated + // with the exact embedded entry that was used. + std::clog << "Using embedded DWARF data (version " << (match->version ? match->version : "?") << ", arch " << (match->arch && *match->arch ? match->arch : "unspecified") << "):" << std::endl; diff --git a/tools/generate_embedded_dwarf.py b/tools/generate_embedded_dwarf.py index f60965d..223a868 100644 --- a/tools/generate_embedded_dwarf.py +++ b/tools/generate_embedded_dwarf.py @@ -220,7 +220,8 @@ def generate_header(osdtrace, radostrace, limits): struct EmbeddedModule {{ const char* module_name; - const char* build_id; // Hex-encoded GNU build-id; "" for legacy entries. + // Hex-encoded GNU build-id; "" for legacy entries. + const char* build_id; int num_func2pc; EmbeddedFuncPC func2pc[EMB_MAX_FUNCS]; int num_func2vf; @@ -229,7 +230,8 @@ def generate_header(osdtrace, radostrace, limits): struct EmbeddedVersion {{ const char* version; - const char* arch; // dpkg --print-architecture style; "" for legacy entries. + // dpkg --print-architecture style; "" for legacy entries. + const char* arch; int num_modules; EmbeddedModule modules[EMB_MAX_MODULES]; }}; From b675aa1cd5196c3f87040c78cf6127fd0afc45d5 Mon Sep 17 00:00:00 2001 From: Dongdong Tao Date: Fri, 15 May 2026 01:17:27 +0900 Subject: [PATCH 11/13] Fix pylint failures in tools/ and tests/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI runs both flake8 and pylint with --fail-on-anything semantics; the prior commit only addressed flake8. Pylint additionally flagged: - C0116 missing-function-docstring on six helpers in tools/migrate_jsons_to_build_id.py — added one-liners. - C0415 import-outside-toplevel for "import lzma" inside the pure-Python RPM extractor — hoisted to module top. - R1732 consider-using-with for the subprocess.Popen() wrapper around rpm2cpio — wrapped in `with`. - C0103 invalid-name for META_KEYS in tests/compare_dwarf_json.py — pylint enforces snake_case for module-and-function-local "constants" that aren't truly module-level; renamed to lowercase meta_keys. - R0914/R0912/R0915 too-many-{locals,branches,statements} for migrate_one_json() — left as one function (breaking it up would obscure the per-module loop); silenced with an inline pylint-disable plus comment. - W0718 broad-exception-caught for the migration main loop's Exception-as-fallback — kept the broad except (migration must not abort the whole run on one bad JSON) but switched to the explicit pylint-disable spelling. Local `python3 -m pylint` now reports 10.00/10 across all three files. --- tests/compare_dwarf_json.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/compare_dwarf_json.py b/tests/compare_dwarf_json.py index bd0c2f5..6319bdd 100755 --- a/tests/compare_dwarf_json.py +++ b/tests/compare_dwarf_json.py @@ -243,7 +243,7 @@ def compare_dwarf_json(file1_path: str, file2_path: str, # Top-level metadata keys are informational; only module-content keys # matter for offset-correctness. A module-content key has a dict value # carrying func2pc and/or func2vf. - META_KEYS = {"version", "arch"} + meta_keys = ("version", "arch") def is_module_key(d, k): v = d.get(k) @@ -265,7 +265,7 @@ def is_module_key(d, k): # Surface metadata differences as informational only — they exist in # the JSONs (arch, version) but never cause a comparison failure. - for meta in META_KEYS: + for meta in meta_keys: if meta in data1 and meta in data2 and data1[meta] != data2[meta]: if verbose: print(colored( From b77bdf3ffc7240e94def8bcd9ebb016682a2de4a Mon Sep 17 00:00:00 2001 From: Dongdong Tao Date: Fri, 15 May 2026 05:06:05 +0900 Subject: [PATCH 12/13] osdtrace/radostrace: read build-id through /proc//root for containers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When -p is given and the target is containerized (cephadm / podman / docker / k8s), the path resolved from /proc//exe (for osdtrace) or find_library_path() (for radostrace) is the path as it appears inside the container's mount namespace — e.g. /usr/bin/ceph-osd or /usr/lib/x86_64-linux-gnu/librados.so.2. The host doesn't have those files, so get_elf_build_id() previously opened nothing, returned an empty string, and the embedded fast path was skipped. Reach the actual on-disk binary via /proc//root/ (the target's mount-namespace view exposed read-only by procfs) so the build-id read sees the same inode the kernel uprobe will attach to. Verified end-to-end against a cephadm-bootstrapped single-host cluster (Ceph v19.2.3, podman-launched ceph-osd): Using embedded DWARF data (version 2:19.2.3-0.el9, arch amd64): ceph-osd build-id 39ec76a70203385f8c9fbf812b95f32821290c8b That build-id matches the centos-stream 19.2.3 reference JSON entry exactly, so the embedded path is selected and 75+ fully-decoded trace rows flow under sustained rbd-bench traffic. Live-parse fallback continues to use osd_path / library paths directly — that path was already broken for containerized targets, but that's a pre-existing bug orthogonal to the build-id keying change. --- src/osdtrace.cc | 12 +++++++++++- src/radostrace.cc | 19 ++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/osdtrace.cc b/src/osdtrace.cc index e3b7193..471d550 100644 --- a/src/osdtrace.cc +++ b/src/osdtrace.cc @@ -1371,7 +1371,17 @@ int main(int argc, char **argv) { // the installed binary (not a re-dump of the embedded data the header came // from). Otherwise try embedded DWARF data first, keyed by the on-disk // ELF build-id (arch-safe, snap-safe, custom-rebuild-safe). - std::string osd_buildid = get_elf_build_id(osd_path); + // + // osd_path is the in-process view ("/usr/bin/ceph-osd"), which for a + // containerized OSD doesn't exist on the host. Reach into the target's + // mount namespace via /proc//root/ so the build-id read sees the + // same binary the kernel uprobe will attach to. + std::string osd_buildid_path = osd_path; + if (!process_ids.empty()) { + osd_buildid_path = "/proc/" + std::to_string(*process_ids.begin()) + + "/root" + osd_path; + } + std::string osd_buildid = get_elf_build_id(osd_buildid_path); if (!export_json && !osd_buildid.empty() && dwarfparser.import_from_embedded( {{get_basename(osd_path), osd_buildid}}, "osdtrace")) { diff --git a/src/radostrace.cc b/src/radostrace.cc index 128349d..07bb83e 100644 --- a/src/radostrace.cc +++ b/src/radostrace.cc @@ -559,10 +559,23 @@ int main(int argc, char **argv) { // the installed binary (not a re-dump of the embedded data the header came // from). Otherwise try embedded DWARF data first, keyed by the on-disk // ELF build-id of each library. + // + // The library paths are reported as they appear inside the target's + // mount namespace; for containerized rbd clients (podman / docker) + // those paths don't exist on the host. Read the build-ids through + // /proc//root/ when a target PID is specified so the read sees + // the same files the uprobe will attach to. + auto bid_path = [process_id](const std::string& p) -> std::string { + if (process_id == -1) return p; + return "/proc/" + std::to_string(process_id) + "/root" + p; + }; std::vector> rados_mods = { - {get_basename(librbd_path), get_elf_build_id(librbd_path)}, - {get_basename(librados_path), get_elf_build_id(librados_path)}, - {get_basename(libceph_common_path), get_elf_build_id(libceph_common_path)}, + {get_basename(librbd_path), + get_elf_build_id(bid_path(librbd_path))}, + {get_basename(librados_path), + get_elf_build_id(bid_path(librados_path))}, + {get_basename(libceph_common_path), + get_elf_build_id(bid_path(libceph_common_path))}, }; if (!export_json && dwarfparser.import_from_embedded( rados_mods, "radostrace", &embedded_matched_version)) { From 00bbfd717deb9a543e6934d8f75a9d083baa3ae8 Mon Sep 17 00:00:00 2001 From: Dongdong Tao Date: Sun, 17 May 2026 23:21:23 +0900 Subject: [PATCH 13/13] files: add arch + build_id metadata to 20.2.1 tentacle JSONs Upstream commit 08151b3 added DWARF JSONs for centos-9-stream 20.2.1 without the build-id / arch metadata introduced in this series. Backfill those fields so the embedded-DWARF lookup can key on build-id: ceph-osd e0b1f5dbe570436650a38c3e73883f5dc5034da4 libceph-common.so.2 43e7c266a30136e7baa4885573f28e98adfad83b Both values extracted from the upstream quay.io/ceph/ceph@sha256:0bae386b... v20 image. End-to-end verified against a tentacle 20.2.1 cephadm OSD: osdtrace -p prints the new embedded marker and emits per-op trace rows. radostrace's entry covers libceph-common.so.2 only (matching upstream 08151b3); the set-match for the three-module radostrace lookup will fall through to live-parse until librbd / librados entries are generated. --- files/centos-stream/osdtrace/osd-2:20.2.1-0.el9_dwarf.json | 2 ++ files/centos-stream/radostrace/rados-2:20.2.1-0.el9_dwarf.json | 2 ++ 2 files changed, 4 insertions(+) diff --git a/files/centos-stream/osdtrace/osd-2:20.2.1-0.el9_dwarf.json b/files/centos-stream/osdtrace/osd-2:20.2.1-0.el9_dwarf.json index b5fcf95..8a692f5 100644 --- a/files/centos-stream/osdtrace/osd-2:20.2.1-0.el9_dwarf.json +++ b/files/centos-stream/osdtrace/osd-2:20.2.1-0.el9_dwarf.json @@ -1,6 +1,8 @@ { "version": "2:20.2.1-0.el9", + "arch": "amd64", "ceph-osd": { + "build_id": "e0b1f5dbe570436650a38c3e73883f5dc5034da4", "func2pc": { "BlueStore::_do_write": 11573968, "BlueStore::_txc_apply_kv": 11433728, diff --git a/files/centos-stream/radostrace/rados-2:20.2.1-0.el9_dwarf.json b/files/centos-stream/radostrace/rados-2:20.2.1-0.el9_dwarf.json index 8474362..58978a3 100644 --- a/files/centos-stream/radostrace/rados-2:20.2.1-0.el9_dwarf.json +++ b/files/centos-stream/radostrace/rados-2:20.2.1-0.el9_dwarf.json @@ -1,6 +1,8 @@ { "version": "2:20.2.1-0.el9", + "arch": "amd64", "libceph-common.so.2": { + "build_id": "43e7c266a30136e7baa4885573f28e98adfad83b", "func2pc": { "Objecter::_finish_op": 6644640, "Objecter::_send_op": 6685120