replace DEBUG compiler define with -d/--debug runtime option

I'm tired of setting CFLAGS and people shouldn't have to
recompile to get debug output.  This lays the foundations
proper option handling and logging levels.

Signed-off-by: Seth Jennings <sjenning@redhat.com>
This commit is contained in:
Seth Jennings 2014-03-07 16:03:53 -06:00
parent 50068a640e
commit 6550dd74f6

View File

@ -42,6 +42,7 @@
#include <string.h>
#include <error.h>
#include <gelf.h>
#include <argp.h>
#include "kpatch.h"
@ -54,6 +55,22 @@
error(2, 0, "unreconcilable difference"); \
})
#define log_debug(format, ...) log(DEBUG, format, ##__VA_ARGS__)
#define log_normal(format, ...) log(NORMAL, format, ##__VA_ARGS__)
#define log(level, format, ...) \
({ \
if (loglevel <= (level)) \
printf(format, ##__VA_ARGS__); \
})
enum loglevel {
DEBUG,
NORMAL
};
static enum loglevel loglevel = NORMAL;
/*******************
* Data structures
@ -236,10 +253,9 @@ void kpatch_create_rela_table(struct kpatch_elf *kelf, struct section *sec)
rela_nr = sec->sh.sh_size / sec->sh.sh_entsize;
alloc_table(&sec->relas, sizeof(struct rela), rela_nr);
#if DEBUG
printf("\n=== rela table for %s (%d entries) ===\n",
log_debug("\n=== rela table for %s (%d entries) ===\n",
sec->base->name, rela_nr);
#endif
/* read and store the rela entries */
for_each_rela(i, rela, &sec->relas) {
if (!gelf_getrela(sec->data, i, &rela->rela))
@ -257,14 +273,13 @@ void kpatch_create_rela_table(struct kpatch_elf *kelf, struct section *sec)
if (!rela->string)
ERROR("could not lookup rela string\n");
}
#if DEBUG
printf("offset %d, type %d, %s %s %d", rela->offset,
log_debug("offset %d, type %d, %s %s %d", rela->offset,
rela->type, rela->sym->name,
(rela->addend < 0)?"-":"+", abs(rela->addend));
if (rela->string)
printf(" (string = %s)", rela->string);
printf("\n");
#endif
log_debug(" (string = %s)", rela->string);
log_debug("\n");
}
}
@ -289,9 +304,7 @@ void kpatch_create_section_table(struct kpatch_elf *kelf)
if (elf_getshdrstrndx(kelf->elf, &shstrndx))
ERROR("elf_getshdrstrndx");
#if DEBUG
printf("=== section list (%zu) ===\n", sections_nr);
#endif
log_debug("=== section list (%zu) ===\n", sections_nr);
for_each_section(i, sec, &kelf->sections) {
scn = elf_nextscn(kelf->elf, scn);
@ -311,11 +324,9 @@ void kpatch_create_section_table(struct kpatch_elf *kelf)
sec->index = elf_ndxscn(scn);
#if DEBUG
printf("ndx %02d, data %p, size %zu, name %s\n",
log_debug("ndx %02d, data %p, size %zu, name %s\n",
sec->index, sec->data->d_buf, sec->data->d_size,
sec->name);
#endif
}
/* Sanity check, one more call to elf_nextscn() should return NULL */
@ -337,9 +348,7 @@ void kpatch_create_symbol_table(struct kpatch_elf *kelf)
alloc_table(&kelf->symbols, sizeof(struct symbol), symbols_nr);
#if DEBUG
printf("\n=== symbol table (%d entries) ===\n", symbols_nr);
#endif
log_debug("\n=== symbol table (%d entries) ===\n", symbols_nr);
/* iterator i declared in for_each_entry() macro */
for_each_symbol(i, sym, &kelf->symbols) {
@ -377,14 +386,13 @@ void kpatch_create_symbol_table(struct kpatch_elf *kelf)
sym->name = sym->sec->name;
}
}
#if DEBUG
printf("sym %02d, type %d, bind %d, ndx %02d, name %s",
log_debug("sym %02d, type %d, bind %d, ndx %02d, name %s",
sym->index, sym->type, sym->bind, sym->sym.st_shndx,
sym->name);
if (sym->sec)
printf(" -> %s", sym->sec->name);
printf("\n");
#endif
log_debug(" -> %s", sym->sec->name);
log_debug("\n");
}
}
@ -502,9 +510,8 @@ void kpatch_compare_correlated_symbols(struct table *table)
kpatch_compare_correlated_symbol(sym);
else
sym->status = NEW;
#if DEBUG
printf("symbol %s is %s\n", sym->name, status_str(sym->status));
#endif
log_debug("symbol %s is %s\n", sym->name, status_str(sym->status));
}
}
@ -690,10 +697,10 @@ void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
if (rela->sym->type != STT_SECTION ||
!rela->sym->sec || !rela->sym->sec->sym)
continue;
#if DEBUG
printf("replacing %s with %s\n",
log_debug("replacing %s with %s\n",
rela->sym->name, rela->sym->sec->sym->name);
#endif
rela->sym = rela->sym->sec->sym;
}
}
@ -706,6 +713,9 @@ void kpatch_dump_kelf(struct kpatch_elf *kelf)
struct rela *rela;
int i, j;
if (loglevel > DEBUG)
return;
printf("\n=== Sections ===\n");
for_each_section(i, sec, &kelf->sections) {
printf("%02d %s (%s)", sec->index, sec->name, status_str(sec->status));
@ -765,12 +775,8 @@ int kpatch_find_changed_functions(struct kpatch_elf *kelf)
return changed;
}
#if DEBUG
#define inc_printf(fmt, ...) \
printf("%*s" fmt, recurselevel, "", ##__VA_ARGS__);
#else
#define inc_printf(fmt, ...);
#endif
log_debug("%*s" fmt, recurselevel, "", ##__VA_ARGS__);
void kpatch_include_symbol(struct symbol *sym, int recurselevel)
{
@ -816,15 +822,15 @@ void kpatch_include_changed_functions(struct kpatch_elf *kelf)
struct symbol *sym;
int i;
#if DEBUG
printf("\n=== Inclusion Tree ===\n");
#endif
log_debug("\n=== Inclusion Tree ===\n");
for_each_symbol(i, sym, &kelf->symbols) {
if (sym->status == CHANGED &&
sym->type == STT_FUNC &&
!sym->include)
!sym->include) {
log_normal("function %s has changed\n", sym->name);
kpatch_include_symbol(sym, 0);
}
if (sym->type == STT_FILE)
sym->include = 1;
@ -850,18 +856,15 @@ void kpatch_generate_output(struct kpatch_elf *kelf, struct kpatch_elf **kelfout
sections_nr++;
}
#if DEBUG
printf("outputting %d sections\n",sections_nr);
#endif
log_debug("outputting %d sections\n",sections_nr);
/* count output symbols */
for_each_symbol(i, sym, &kelf->symbols) {
if (i == 0 || sym->include)
symbols_nr++;
}
#if DEBUG
printf("outputting %d symbols\n",symbols_nr);
#endif
log_debug("outputting %d symbols\n",symbols_nr);
/* allocate output kelf */
out = malloc(sizeof(*out));
@ -966,10 +969,8 @@ void kpatch_create_rela_section(struct section *sec, int link)
/* reindex and copy into buffer */
for_each_rela(i, rela, &sec->relas) {
#if DEBUG
if (!rela->sym || !rela->sym->twino)
ERROR("expected rela symbol");
#endif
symndx = rela->sym->twino->index;
type = GELF_R_TYPE(rela->rela.r_info);
rela->rela.r_info = GELF_R_INFO(symndx, type);
@ -999,7 +1000,6 @@ void kpatch_create_rela_sections(struct kpatch_elf *kelf)
kpatch_create_rela_section(sec, link);
}
#if DEBUG
void print_strtab(char *buf, size_t size)
{
int i;
@ -1011,7 +1011,6 @@ void print_strtab(char *buf, size_t size)
printf("%c",buf[i]);
}
}
#endif
void kpatch_create_shstrtab(struct kpatch_elf *kelf)
{
@ -1044,22 +1043,21 @@ void kpatch_create_shstrtab(struct kpatch_elf *kelf)
offset += len;
}
#if DEBUG
if (offset != size)
ERROR("shstrtab size mismatch");
#endif
shstrtab->data->d_buf = buf;
shstrtab->data->d_size = size;
#if DEBUG
printf("shstrtab: ");
print_strtab(buf, size);
printf("\n");
if (loglevel <= DEBUG) {
printf("shstrtab: ");
print_strtab(buf, size);
printf("\n");
for_each_section(i, sec, &kelf->sections)
printf("%s @ shstrtab offset %d\n",sec->name,sec->sh.sh_name);
#endif
for_each_section(i, sec, &kelf->sections)
printf("%s @ shstrtab offset %d\n",
sec->name, sec->sh.sh_name);
}
}
void kpatch_create_strtab(struct kpatch_elf *kelf)
@ -1103,22 +1101,21 @@ void kpatch_create_strtab(struct kpatch_elf *kelf)
offset += len;
}
#if DEBUG
if (offset != size)
ERROR("shstrtab size mismatch");
#endif
strtab->data->d_buf = buf;
strtab->data->d_size = size;
#if DEBUG
printf("strtab: ");
print_strtab(buf, size);
printf("\n");
if (loglevel <= DEBUG) {
printf("strtab: ");
print_strtab(buf, size);
printf("\n");
for_each_symbol(i, sym, &kelf->symbols)
printf("%s @ strtab offset %d\n",sym->name,sym->sym.st_name);
#endif
for_each_symbol(i, sym, &kelf->symbols)
printf("%s @ strtab offset %d\n",
sym->name, sym->sym.st_name);
}
}
void kpatch_create_symtab(struct kpatch_elf *kelf)
@ -1222,16 +1219,64 @@ void kpatch_write_output_elf(struct kpatch_elf *kelf, Elf *elf, char *outfile)
}
}
struct arguments {
char *args[3];
int debug;
};
static char args_doc[] = "original.o patched.o output.o";
static struct argp_option options[] = {
{"debug", 'd', 0, 0, "Show debug output" },
{ 0 }
};
static error_t parse_opt (int key, char *arg, struct argp_state *state)
{
/* Get the input argument from argp_parse, which we
know is a pointer to our arguments structure. */
struct arguments *arguments = state->input;
switch (key)
{
case 'd':
arguments->debug = 1;
break;
case ARGP_KEY_ARG:
if (state->arg_num >= 3)
/* Too many arguments. */
argp_usage (state);
arguments->args[state->arg_num] = arg;
break;
case ARGP_KEY_END:
if (state->arg_num < 3)
/* Not enough arguments. */
argp_usage (state);
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
static struct argp argp = { options, parse_opt, args_doc, 0 };
int main(int argc, char *argv[])
{
struct kpatch_elf *kelf_base, *kelf_patched, *kelf_out;
char *outfile;
struct arguments arguments;
arguments.debug = 0;
argp_parse (&argp, argc, argv, 0, 0, &arguments);
if (arguments.debug)
loglevel = DEBUG;
elf_version(EV_CURRENT);
kelf_base = kpatch_elf_open(argv[1]);
kelf_patched = kpatch_elf_open(argv[2]);
outfile = argv[3];
kelf_base = kpatch_elf_open(arguments.args[0]);
kelf_patched = kpatch_elf_open(arguments.args[1]);
outfile = arguments.args[2];
kpatch_compare_elf_headers(kelf_base->elf, kelf_patched->elf);
kpatch_check_program_headers(kelf_base->elf);
@ -1256,9 +1301,7 @@ int main(int argc, char *argv[])
kpatch_replace_sections_syms(kelf_patched);
kpatch_include_changed_functions(kelf_patched);
#if DEBUG
kpatch_dump_kelf(kelf_patched);
#endif
/* Generate the output elf */
kpatch_generate_output(kelf_patched, &kelf_out);
@ -1266,9 +1309,7 @@ int main(int argc, char *argv[])
kpatch_create_shstrtab(kelf_out);
kpatch_create_strtab(kelf_out);
kpatch_create_symtab(kelf_out);
#if DEBUG
kpatch_dump_kelf(kelf_out);
#endif
kpatch_write_output_elf(kelf_out, kelf_patched->elf, outfile);