/* The intent is to use get_jited_program_text() for small test * programs written in BPF assembly, thus assume that 32 local labels * would be sufficient.
*/ #define MAX_LOCAL_LABELS 32
/* Local labels are encoded as 'L42', this requires 4 bytes of storage: * 3 characters + zero byte
*/ #define LOCAL_LABEL_LEN 4
*ref_type = LLVMDisassembler_ReferenceType_InOut_None;
*ref_name = NULL; if (type != LLVMDisassembler_ReferenceType_In_Branch) return NULL; /* Depending on labels->print_phase either discover local labels or * return a name assigned with local jump target: * - if print_phase is true and ref_value is in labels->pcs, * return corresponding labels->name. * - if print_phase is false, save program-local jump targets * in labels->pcs;
*/ if (labels->print_phase) { for (i = 0; i < labels->cnt; ++i) if (labels->pcs[i] == ref_value) return labels->names[i];
} else { if (labels->cnt < MAX_LOCAL_LABELS && ref_value < labels->prog_len)
labels->pcs[labels->cnt++] = ref_value;
} return NULL;
}
staticint disasm_insn(LLVMDisasmContextRef ctx, uint8_t *image, __u32 len, __u32 pc, char *buf, __u32 buf_sz)
{ int i, cnt;
cnt = LLVMDisasmInstruction(ctx, image + pc, len - pc, pc,
buf, buf_sz); if (cnt > 0) return cnt;
PRINT_FAIL("Can't disasm instruction at offset %d:", pc); for (i = 0; i < 16 && pc + i < len; ++i)
printf(" %02x", image[pc + i]);
printf("\n"); return -EINVAL;
}
staticint cmp_u32(constvoid *_a, constvoid *_b)
{
__u32 a = *(__u32 *)_a;
__u32 b = *(__u32 *)_b;
if (a < b) return -1; if (a > b) return 1; return 0;
}
/* discover labels */
labels.prog_len = len;
pc = 0; while (pc < len) {
cnt = disasm_insn(ctx, image, len, pc, buf, 1); if (cnt < 0) {
err = cnt; goto out;
}
pc += cnt;
}
qsort(labels.pcs, labels.cnt, sizeof(*labels.pcs), cmp_u32); for (i = 0; i < labels.cnt; ++i) /* gcc is unable to infer upper bound for labels.cnt and assumes * it to be U32_MAX. U32_MAX takes 10 decimal digits. * snprintf below prints into labels.names[*], * which has space only for two digits and a letter. * To avoid truncation warning use (i % MAX_LOCAL_LABELS), * which informs gcc about printed value upper bound.
*/
snprintf(labels.names[i], sizeof(labels.names[i]), "L%d", i % MAX_LOCAL_LABELS);
/* now print with labels */
labels.print_phase = true;
pc = 0; while (pc < len) {
cnt = disasm_insn(ctx, image, len, pc, buf, sizeof(buf)); if (cnt < 0) {
err = cnt; goto out;
}
label_pc = bsearch(&pc, labels.pcs, labels.cnt, sizeof(*labels.pcs), cmp_u32);
label = "";
colon = ""; if (label_pc) {
label = labels.names[label_pc - labels.pcs];
colon = ":";
}
fprintf(text_out, "%x:\t", pc); for (i = 0; i < cnt; ++i)
fprintf(text_out, "%02x ", image[pc + i]); for (i = cnt * 3; i < 12 * 3; ++i)
fputc(' ', text_out);
fprintf(text_out, "%s%s%s\n", label, colon, buf);
pc += cnt;
}
out: if (triple)
LLVMDisposeMessage(triple); if (ctx)
LLVMDisasmDispose(ctx); return err;
}
int get_jited_program_text(int fd, char *text, size_t text_sz)
{ struct bpf_prog_info info = {};
__u32 info_len = sizeof(info);
__u32 jited_funcs, len, pc;
__u32 *func_lens = NULL;
FILE *text_out = NULL;
uint8_t *image = NULL; int i, err = 0;
if (!llvm_initialized) {
LLVMInitializeAllTargetInfos();
LLVMInitializeAllTargetMCs();
LLVMInitializeAllDisassemblers();
llvm_initialized = 1;
}
/* first call is to find out jited program len */
err = bpf_prog_get_info_by_fd(fd, &info, &info_len); if (!ASSERT_OK(err, "bpf_prog_get_info_by_fd #1")) goto out;
len = info.jited_prog_len;
image = malloc(len); if (!ASSERT_OK_PTR(image, "malloc(info.jited_prog_len)")) {
err = -ENOMEM; goto out;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.