return sym ? sym->alias : NULL;
}
+/*
+ * Also match the symbol end address which can be used for a bounds comparison.
+ */
+struct symbol *find_symbol_containing_inclusive(const struct section *sec,
+ unsigned long offset)
+{
+ struct symbol *sym = find_symbol_containing(sec, offset);
+
+ if (!sym && offset)
+ sym = find_symbol_containing(sec, offset - 1);
+
+ return sym;
+}
+
/*
* Returns size of hole starting at @offset.
*/
struct symbol *find_symbol_by_name(const struct elf *elf, const char *name);
struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *name);
struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset);
+struct symbol *find_symbol_containing_inclusive(const struct section *sec, unsigned long offset);
int find_symbol_hole_containing(const struct section *sec, unsigned long offset);
struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset);
struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
is_uncorrelated_static_local(sym) ||
is_local_label(sym) ||
is_string_sec(sym->sec) ||
+ (is_rodata_sec(sym->sec) && !is_object_sym(sym)) ||
is_initcall_sym(sym) ||
is_addressable_sym(sym) ||
is_special_section(sym->sec) ||
goto found_sym;
/* No dedicated section; find the symbol manually */
- sym = find_symbol_containing(sec, arch_adjusted_addend(reloc));
+ sym = find_symbol_containing_inclusive(sec, arch_adjusted_addend(reloc));
if (!sym) {
/*
* This is presumably an .altinstr_replacement section which is
if (!sec_size(sec))
return 1;
+ /*
+ * .rodata is a mixed bag of named objects and anonymous data.
+ *
+ * Convert section symbol references to named object symbols
+ * when possible, to preserve pointer identity for const
+ * structs like file_operations. Otherwise a section symbol is
+ * fine.
+ */
+ if (is_rodata_sec(sec))
+ return 0;
+
/*
* This can happen for special section references to weak code
* whose symbol has been stripped by the linker.
static bool is_uncorrelated_section(struct section *sec)
{
return is_string_sec(sec) ||
- strstarts(sec->name, ".rodata") ||
strstarts(sec->name, ".data..Lubsan") || /* GCC */
strstarts(sec->name, ".data..L__unnamed_"); /* Clang */
}