tools/objtool/arch/x86/decode.c

Source file repositories/reference/linux-study-clean/tools/objtool/arch/x86/decode.c

File Facts

System
Linux kernel
Corpus path
tools/objtool/arch/x86/decode.c
Extension
.c
Size
18958 bytes
Lines
979
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

if (o + insn.length > offset) {
			*insn_off = o;
			*insn_len = insn.length;
			return;
		}

		o += insn.length;
	}
}

u64 arch_adjusted_addend(struct reloc *reloc)
{
	unsigned int type = reloc_type(reloc);
	s64 addend = reloc_addend(reloc);
	unsigned long insn_off;
	unsigned int insn_len;

	if (type == R_X86_64_PLT32)
		return addend + 4;

	if (type != R_X86_64_PC32 || !is_text_sec(reloc->sec->base))
		return addend;

	scan_for_insn(reloc->sec->base, reloc_offset(reloc),
		      &insn_off, &insn_len);

	return addend + insn_off + insn_len - reloc_offset(reloc);
}

unsigned long arch_jump_destination(struct instruction *insn)
{
	return insn->offset + insn->len + insn->immediate;
}

bool arch_pc_relative_reloc(struct reloc *reloc)
{
	/*
	 * All relocation types where P (the address of the target)
	 * is included in the computation.
	 */
	switch (reloc_type(reloc)) {
	case R_X86_64_PC8:
	case R_X86_64_PC16:
	case R_X86_64_PC32:
	case R_X86_64_PC64:

	case R_X86_64_PLT32:
	case R_X86_64_GOTPC32:
	case R_X86_64_GOTPCREL:
		return true;

	default:
		break;
	}

	return false;
}

#define ADD_OP(op) \
	if (!(op = calloc(1, sizeof(*op)))) \
		return -1; \
	else for (*ops_list = op, ops_list = &op->next; op; op = NULL)

/*
 * Helpers to decode ModRM/SIB:
 *
 * r/m| AX  CX  DX  BX |  SP |  BP |  SI  DI |
 *    | R8  R9 R10 R11 | R12 | R13 | R14 R15 |
 * Mod+----------------+-----+-----+---------+
 * 00 |    [r/m]       |[SIB]|[IP+]|  [r/m]  |
 * 01 |  [r/m + d8]    |[S+d]|   [r/m + d8]  |
 * 10 |  [r/m + d32]   |[S+D]|   [r/m + d32] |
 * 11 |                   r/ m               |
 */

#define mod_is_mem()	(modrm_mod != 3)
#define mod_is_reg()	(modrm_mod == 3)

#define is_RIP()   ((modrm_rm & 7) == CFI_BP && modrm_mod == 0)
#define have_SIB() ((modrm_rm & 7) == CFI_SP && mod_is_mem())

/*
 * Check the ModRM register. If there is a SIB byte then check with
 * the SIB base register. But if the SIB base is 5 (i.e. CFI_BP) and
 * ModRM mod is 0 then there is no base register.
 */
#define rm_is(reg) (have_SIB() ? \
		    sib_base == (reg) && sib_index == CFI_SP && \
		    (sib_base != CFI_BP || modrm_mod != 0) :	\
		    modrm_rm == (reg))

Annotation

Implementation Notes