tools/testing/selftests/bpf/jit_disasm_helpers.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/bpf/jit_disasm_helpers.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/jit_disasm_helpers.c
Extension
.c
Size
6431 bytes
Lines
255
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct local_labels {
	bool print_phase;
	__u32 prog_len;
	__u32 cnt;
	__u32 pcs[MAX_LOCAL_LABELS];
	char names[MAX_LOCAL_LABELS][LOCAL_LABEL_LEN];
};

static const char *lookup_symbol(void *data, uint64_t ref_value, uint64_t *ref_type,
				 uint64_t ref_pc, const char **ref_name)
{
	struct local_labels *labels = data;
	uint64_t type = *ref_type;
	int i;

	*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;
}

static int 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;
}

static int cmp_u32(const void *_a, const void *_b)
{
	__u32 a = *(__u32 *)_a;
	__u32 b = *(__u32 *)_b;

	if (a < b)
		return -1;
	if (a > b)
		return 1;
	return 0;
}

static int disasm_one_func(FILE *text_out, uint8_t *image, __u32 len)
{
	char *label, *colon, *triple = NULL;
	LLVMDisasmContextRef ctx = NULL;
	struct local_labels labels = {};
	__u32 *label_pc, pc;
	int i, cnt, err = 0;
	char buf[64];
	char *cpu, *features;

	triple = LLVMGetDefaultTargetTriple();

	cpu = LLVMGetHostCPUName();
	features = LLVMGetHostCPUFeatures();

	ctx = LLVMCreateDisasmCPUFeatures(triple, cpu, features, &labels, 0, NULL, lookup_symbol);

	LLVMDisposeMessage(cpu);
	LLVMDisposeMessage(features);

	if (!ASSERT_OK_PTR(ctx, "LLVMCreateDisasmCPUFeatures")) {
		err = -EINVAL;
		goto out;
	}

Annotation

Implementation Notes