This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
[PATCH]PR 4886: validate debuginfo based on build-id
- From: Wenji Huang <wenji dot huang at oracle dot com>
- To: systemtap at sources dot redhat dot com
- Date: Tue, 15 Jul 2008 13:08:14 +0800
- Subject: [PATCH]PR 4886: validate debuginfo based on build-id
The patch is to provide sanity check of debuginfo(PR 4886) based on
build-id, as described in
http://fedoraproject.org/wiki/Releases/FeatureBuildId.
There are some requisites for it to work:
binutils-2.17.50.0.17 or later
Kernel 2.6.23 or later
elfutils 0.128 or later (compilation required)
Otherwise, the check will be skipped.
Already done some tests on x86/x86_64, relocate/non-relocate kernel.
Any comment/reply are welcome.
Regards,
Wenji
diff --git a/main.cxx b/main.cxx
index 05a137b..8cb8163 100644
--- a/main.cxx
+++ b/main.cxx
@@ -318,6 +318,7 @@ main (int argc, char * const argv [])
s.unoptimized = false;
s.suppress_warnings = false;
s.listing_mode = false;
+ s.build_id_len = 0;
#ifdef ENABLE_PROLOGUES
s.prologue_searching = true;
diff --git a/session.h b/session.h
index 734c8d7..43b26d3 100644
--- a/session.h
+++ b/session.h
@@ -178,6 +178,10 @@ struct systemtap_session
void print_error (const semantic_error& e);
void print_warning (const std::string& w, const token* tok = 0);
+ //build-id for validating debuginfo
+ unsigned char *build_id_bits;
+ GElf_Addr build_id_vaddr;
+ int build_id_len;
// reNB: new POD members likely need to be explicitly cleared in the ctor.
};
diff --git a/tapsets.cxx b/tapsets.cxx
index 21c9fb5..28d11b4 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -3796,6 +3796,32 @@ validate_module_elf (Dwfl_Module *mod, const char *name, base_query *q)
<< " ELF machine " << expect_machine
<< " (code " << elf_machine << ")"
<< "\n";
+
+ //extract build-id from kernel debuginfo file
+ int build_id_len = 0;
+ unsigned char *build_id_bits;
+ GElf_Addr build_id_vaddr;
+
+ //FIXME: currently just verify kernel debug file
+ if (!q->dw.module_name.compare("kernel") &&
+ (build_id_len=dwfl_module_build_id(mod,
+ (const unsigned char **)&build_id_bits,
+ &build_id_vaddr)) > 0)
+ {
+ q->sess.build_id_len = build_id_len;
+ void *copy = malloc(build_id_len);
+ q->sess.build_id_bits = (unsigned char *)memcpy(copy,
+ build_id_bits,
+ build_id_len);
+ q->sess.build_id_vaddr = build_id_vaddr;
+
+ if (q->sess.verbose > 2) {
+ clog << "Found build-id in " << debug_filename
+ << ", length " << q->sess.build_id_len;
+ clog << ", end at 0x" << hex << q->sess.build_id_vaddr
+ << dec << endl;
+ }
+ }
}
static int
diff --git a/translate.cxx b/translate.cxx
index 215d7ff..fcf8247 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -1109,12 +1109,68 @@ c_unparser::emit_module_init ()
<< ");";
o->newline() << "rc = -EINVAL;";
o->newline(-1) << "}";
-
- // XXX: perform buildid-based checking if able
-
+
o->newline(-1) << "}";
o->newline() << "if (rc) goto out;";
+ // perform buildid-based checking if able
+ if (session->build_id_len > 0) {
+ o->newline() << "{";
+ //initialize data for matching build-id
+ o->newline(1) << "unsigned char *build_id_bits = \"";
+ for (int j = 0; j < session->build_id_len; j++)
+ o->line() << "\\x"
+ << hex << (unsigned short)*(session->build_id_bits+j)
+ << dec;
+ o->line() << "\";";
+
+ o->newline() << "unsigned long build_id_start, build_id_stop = "
+ << " (unsigned long) 0x"
+ << hex << session->build_id_vaddr << dec
+ << ";";
+
+ o->newline() << "build_id_start = build_id_stop - "
+ << session->build_id_len << ";";
+
+ //the address should be bigger than "_stext" address
+ //NB: _stext is the relocation name
+ o->newline() << "if (build_id_start < _stp_module_relocate(\"kernel\""
+ << " ,\"_stext\" , 0)) {";
+ o->newline(1) << "_stp_error(\"Incorrect __start_notes address\");";
+ o->newline() << "rc = -EINVAL;";
+ o->newline() << "goto out;";
+ o->newline(-1) << "}";
+
+ //compare build-id
+ o->newline() << "if (memcmp(build_id_bits"
+ << ", (unsigned char *) build_id_start"
+ << ", " << session->build_id_len
+ << ")) {";
+ o->newline(1) << "_stp_printf(\"Expected build-id:\\n\");";
+ o->newline() << "for (i=0;i<"
+ << session->build_id_len
+ << ";i++)";
+ o->newline(1) << "_stp_printf(\" 0x%x\","
+ << "*(build_id_bits+i));";
+
+ o->newline(-1) << "_stp_printf(\"\\nActual build-id:\\n\");";
+ o->newline() << "for (i=0;i<"
+ << session->build_id_len
+ << ";i++)";
+ o->newline(1) << "_stp_printf(\" 0x%x\","
+ << "*((unsigned char *)(build_id_start+i)));";
+
+ o->newline(-1) << "_stp_printf(\"\\n\");";
+ o->newline() << "_stp_print_flush();";
+ o->newline() << "_stp_error(\"build-id mismatch between "
+ << "debuginfo and kernel\");";
+ o->newline() << "rc = -EINVAL;";
+ o->newline() << "goto out;";
+ o->newline(-1) << "}";
+
+ o->newline(-1) << "}";
+ }
+
o->newline() << "(void) probe_point;";
o->newline() << "(void) i;";
o->newline() << "(void) j;";