config KALLSYMS_BASE_RELATIVE
bool
depends on KALLSYMS
- default !IA64
+ default !IA64 && !(TILE && 64BIT)
help
Instead of emitting them as absolute values in the native word size,
emit the symbol references in the kallsyms table as 32-bit entries,
- each containing either an absolute value in the range [0, S32_MAX] or
- a relative value in the range [base, base + S32_MAX], where base is
- the lowest relative symbol address encountered in the image.
+ each containing a relative value in the range [base, base + U32_MAX]
+ or, when KALLSYMS_ABSOLUTE_PERCPU is in effect, each containing either
+ an absolute value in the range [0, S32_MAX] or a relative value in the
+ range [base, base + S32_MAX], where base is the lowest relative symbol
+ address encountered in the image.
On 64-bit builds, this reduces the size of the address table by 50%,
but more importantly, it results in entries whose values are build
if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
return kallsyms_addresses[idx];
- /* positive offsets are absolute values */
+ /* values are unsigned offsets if --absolute-percpu is not in effect */
+ if (!IS_ENABLED(CONFIG_KALLSYMS_ABSOLUTE_PERCPU))
+ return kallsyms_relative_base + (u32)kallsyms_offsets[idx];
+
+ /* ...otherwise, positive offsets are absolute values */
if (kallsyms_offsets[idx] >= 0)
return kallsyms_offsets[idx];
- /* negative offsets are relative to kallsyms_relative_base - 1 */
+ /* ...and negative offsets are relative to kallsyms_relative_base - 1 */
return kallsyms_relative_base - 1 - kallsyms_offsets[idx];
}
for (i = 0; i < table_cnt; i++) {
if (base_relative) {
long long offset;
+ int overflow;
- if (symbol_absolute(&table[i])) {
+ if (!absolute_percpu) {
+ offset = table[i].addr - relative_base;
+ overflow = (offset < 0 || offset > UINT_MAX);
+ } else if (symbol_absolute(&table[i])) {
offset = table[i].addr;
- if (offset < 0 || offset > INT_MAX) {
- fprintf(stderr, "kallsyms failure: "
- "absolute symbol value %#llx out of range in relative mode\n",
- table[i].addr);
- exit(EXIT_FAILURE);
- }
+ overflow = (offset < 0 || offset > INT_MAX);
} else {
offset = relative_base - table[i].addr - 1;
- if (offset < INT_MIN || offset >= 0) {
- fprintf(stderr, "kallsyms failure: "
- "relative symbol value %#llx out of range in relative mode\n",
- table[i].addr);
- exit(EXIT_FAILURE);
- }
+ overflow = (offset < INT_MIN || offset >= 0);
+ }
+ if (overflow) {
+ fprintf(stderr, "kallsyms failure: "
+ "%s symbol value %#llx out of range in relative mode\n",
+ symbol_absolute(&table[i]) ? "absolute" : "relative",
+ table[i].addr);
+ exit(EXIT_FAILURE);
}
printf("\t.long\t%#x\n", (int)offset);
} else if (!symbol_absolute(&table[i])) {
{
unsigned int i;
- if (kernel_start_addr > 0) {
- /*
- * If the kernel start address was specified, use that as
- * the relative base rather than going through the table,
- * since it should be a reasonable default, and values below
- * it will be ignored anyway.
- */
- relative_base = kernel_start_addr;
- } else {
- relative_base = -1ULL;
- for (i = 0; i < table_cnt; i++)
- if (!symbol_absolute(&table[i]) &&
- table[i].addr < relative_base)
- relative_base = table[i].addr;
- }
+ relative_base = -1ULL;
+ for (i = 0; i < table_cnt; i++)
+ if (!symbol_absolute(&table[i]) &&
+ table[i].addr < relative_base)
+ relative_base = table[i].addr;
}
int main(int argc, char **argv)