Objtool 迁移的一些记录
Contents
objtool 执行顺序:
1 | main -> objtool_run -> objtool_open_read -> check -> decode_sections |
目前问题在于 decode_instructions
函数中,在这段if
判断语句中会出现问题:
1 | if (!find_insn(file, sec, func->offset)) { |
解决,将
decode_instructions
函数中以下代码注释:
1
2
3
4
5
6 struct symbol *obj_sym = find_object_containing(sec, offset);
if (obj_sym) {
/* This is data in the middle of text section, skip it */
next_offset = obj_sym->offset + obj_sym->len;
continue;
}原因:会有部分指令在这里跳过,导致后面的哈希表无法加入这些指令:
hash_add(file->insn_hash, &insn->hash, sec_offset_hash(sec, insn->offset));
1 | struct instruction *find_insn(struct objtool_file *file, |
一些宏的定义:
1 | /** |
1 | list_for_each_entry(sec, &file->elf->sections, list) |
1 | for (insn = find_insn(file, _sec, 0); \ |
接下来要做的事:
-
解决
unreachable instruction
警告。 -
解决
call without frame pointer save/setup
警告。 -
解决
unannotated intra-function call
警告。
unreachable instruction
1 | security/keys/gc.o: warning: objtool: key_gc_unused_keys.constprop.0+0x8c: unreachable instruction |
主要问题在于static int add_dead_ends(struct objtool_file *file)
函数,
这个函数会检测当前指令是否是dead_end
:
1 | /* |
如果当前的 section 不是.rela.discard.unreachable
,则说明是dead_end
,但是这个并不是很准确,
所以导致了以上问题。
目前解决方法是手动往sections
中加入.rela.discard.unreachable
:
1 | asm volatile(__stringify_label(c) ":\n\t" \ |
但是目前还没排查到什么原因没有生效。补充:并不是没有生效,是生效了,但是仍然
报警告。
我认为是这个宏的调用问题。
…/ua/util.o: warning: objtool: sysvipc_proc_open+0x50: unreachable instruction
经过 debug,发现是因为validate_branch
函数中的这一段:
1 | case INSN_JUMP_CONDITIONAL: |
因为sysvipc_proc_open+0x50
的上一个指令sysvipc_proc_open+0x4c
是无条件跳转指令,
所以导致直接return 0
结束函数,导致后面的0x50
无法继续解析。
由 objdumpaarch64-linux-gnu-objdump -d ../ua/util.o
找出相对的指令如下:
1 | 2ec: 14000024 b 37c <sysvipc_proc_open+0xdc> |
好吧,又经过一段排查,发现这应该就是一个主要原因了。
主要原因:aarch64 的无条件跳转指令 b
之后的指令如果
在其它地方没有被跳转过来,那么这个指令的visited
就为0
,
它将会报以上警告。
call without frame pointer save/setup
查看 patch。
一些信息:
1 |
|
关键在于has_valid_stack_frame(struct insn_state *state)
函数:
1 |
|
1 | if (opts.stackval && func && !is_fentry_call(insn) && |
调用栈帧关系:
1 | check -> validate_functions -> validate_section -> validate_symbol |
要使这个函数返回 true,必须满足以下条件:
- CFA 的基址是否为
CFI_BP
,并且检查帧指针(FP x29)和返回地址寄存器(LR x30)的基址和
偏移量是否符合预期。是否符合预期的要求:
-
帧指针 FP 应该位于 CFA 的负偏移量位置。
-
返回地址寄存器 LR 应该与 CFA 的负偏移量 +8 的位置。
此处就是正常的函数调用栈帧的变化,在其它笔记中有说明。
-
- 如果存在 drap(可能是某种标志位,暂时没查),并且帧指针的基址与 CFI_BP 相等,那么函数也会返回 true。
主要问题:
没有成功计算出 cfi->cfa.base
的值,这个值应该要转换成 CFI_BP
的值。
unannotated intra-function
查看 patch
drivers/irqchip/irq-gic-v3.o: warning: objtool: __gic_get_ppi_index.part.0() is missing an ELF size annotation
drivers/irqchip/irq-gic-v3.o: warning: objtool: gic_dist_base_alias.part.0() is missing an ELF size annotation
Author: xun
Link: http://blog.fooo.in/2023/08/16/assembly/objtool-amd-impl/
License:
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。