diff --git a/defs.h b/defs.h index 98650e8..9f40045 100644 --- a/defs.h +++ b/defs.h @@ -2240,6 +2240,9 @@ struct offset_table { /* stash of commonly-used offsets */ long mnt_namespace_nr_mounts; long mount_mnt_node; long log_caller_id; + long module_sect_attr_battr; + long bin_attribute_attr; + long attribute_name; }; struct size_table { /* stash of commonly-used sizes */ @@ -2911,8 +2914,9 @@ struct symbol_table_data { #define MODSECT_V1 (0x2000) #define MODSECT_V2 (0x4000) #define MODSECT_V3 (0x8000) -#define MODSECT_VMASK (MODSECT_V1|MODSECT_V2|MODSECT_V3) #define NO_STRIP (0x10000) +#define MODSECT_V4 (0x20000) +#define MODSECT_VMASK (MODSECT_V1|MODSECT_V2|MODSECT_V3|MODSECT_V4) #define NO_LINE_NUMBERS() ((st->flags & GDB_SYMS_PATCHED) && !(kt->flags2 & KASLR)) diff --git a/symbols.c b/symbols.c index cbc9ed1..5ad2a59 100644 --- a/symbols.c +++ b/symbols.c @@ -10233,6 +10233,7 @@ dump_offset_table(char *spec, ulong makestruct) OFFSET(module_sect_attrs_attrs)); fprintf(fp, " module_sect_attrs_nsections: %ld\n", OFFSET(module_sect_attrs_nsections)); + fprintf(fp, " module_sect_attr_battr: %ld\n", OFFSET(module_sect_attr_battr)); fprintf(fp, " module_sect_attr_mattr: %ld\n", OFFSET(module_sect_attr_mattr)); fprintf(fp, " module_sect_attr_name: %ld\n", @@ -10241,12 +10242,14 @@ dump_offset_table(char *spec, ulong makestruct) OFFSET(module_sect_attr_address)); fprintf(fp, " attribute_owner: %ld\n", OFFSET(attribute_owner)); + fprintf(fp, " attribute_name: %ld\n", OFFSET(attribute_name)); fprintf(fp, " module_sect_attr_attr: %ld\n", OFFSET(module_sect_attr_attr)); fprintf(fp, " module_sections_attrs: %ld\n", OFFSET(module_sections_attrs)); fprintf(fp, " module_attribute_attr: %ld\n", OFFSET(module_attribute_attr)); + fprintf(fp, " bin_attribute_attr: %ld\n", OFFSET(bin_attribute_attr)); fprintf(fp, " module_kallsyms_start: %ld\n", OFFSET(module_kallsyms_start)); @@ -13165,7 +13168,14 @@ add_symbol_file_kallsyms(struct load_module *lm, struct gnu_request *req) MEMBER_OFFSET_INIT(attribute_owner, "attribute", "owner"); - if (VALID_MEMBER(module_sect_attrs_attrs) && + /* Linux 5.8 and later */ + MEMBER_OFFSET_INIT(module_sect_attr_battr, "module_sect_attr", "battr"); + MEMBER_OFFSET_INIT(bin_attribute_attr, "bin_attribute", "attr"); + MEMBER_OFFSET_INIT(attribute_name, "attribute", "name"); + + if (VALID_MEMBER(module_sect_attr_battr)) + st->flags |= MODSECT_V4; + else if (VALID_MEMBER(module_sect_attrs_attrs) && VALID_MEMBER(module_sect_attr_mattr) && VALID_MEMBER(module_attribute_attr) && VALID_MEMBER(module_sect_attrs_nsections)) @@ -13185,7 +13195,7 @@ add_symbol_file_kallsyms(struct load_module *lm, struct gnu_request *req) (INVALID_MEMBER(attribute_owner) && (st->flags & (MODSECT_V1|MODSECT_V2))) || INVALID_MEMBER(module_sect_attrs) || - INVALID_MEMBER(module_sect_attr_name) || + (INVALID_MEMBER(module_sect_attr_name) && !(st->flags & MODSECT_V4)) || INVALID_MEMBER(module_sect_attr_address)) { if (CRASHDEBUG(1)) error(WARNING, @@ -13216,6 +13226,7 @@ add_symbol_file_kallsyms(struct load_module *lm, struct gnu_request *req) nsections = UNUSED; break; case MODSECT_V3: + case MODSECT_V4: array_entry = vaddr + OFFSET(module_sect_attrs_attrs); if (!readmem(vaddr + OFFSET(module_sect_attrs_nsections), KVADDR, &nsections, sizeof(int), @@ -13230,6 +13241,7 @@ add_symbol_file_kallsyms(struct load_module *lm, struct gnu_request *req) fprintf(fp, "%s:\n", lm->mod_namelist); name_type = MEMBER_TYPE("module_sect_attr", "name"); + req->buf = GETBUF(buflen = 1024); retval = FALSE; @@ -13245,6 +13257,10 @@ add_symbol_file_kallsyms(struct load_module *lm, struct gnu_request *req) attribute = array_entry + OFFSET(module_sect_attr_mattr) + OFFSET(module_attribute_attr); break; + case MODSECT_V4: + attribute = array_entry + OFFSET(module_sect_attr_battr) + + OFFSET(bin_attribute_attr); + break; } if (st->flags & (MODSECT_V1|MODSECT_V2)) @@ -13253,23 +13269,35 @@ add_symbol_file_kallsyms(struct load_module *lm, struct gnu_request *req) owner = UNUSED; address = array_entry + OFFSET(module_sect_attr_address); - switch (name_type) - { - case TYPE_CODE_ARRAY: - name = array_entry + OFFSET(module_sect_attr_name); - break; - case TYPE_CODE_PTR: - if (!readmem(array_entry + OFFSET(module_sect_attr_name), - KVADDR, &name, sizeof(void *), - "module_sect_attr.name", RETURN_ON_ERROR|QUIET)) { + + if (st->flags & MODSECT_V4) { + if (!readmem(array_entry + OFFSET(module_sect_attr_battr) + + OFFSET(bin_attribute_attr) + OFFSET(attribute_name), + KVADDR, &name, sizeof(void *), + "module_sect_attr.battr.attr.name", RETURN_ON_ERROR|QUIET)) { done = TRUE; retval = FALSE; continue; } - break; - default: - done = TRUE; - retval = FALSE; + } else { + switch (name_type) + { + case TYPE_CODE_ARRAY: + name = array_entry + OFFSET(module_sect_attr_name); + break; + case TYPE_CODE_PTR: + if (!readmem(array_entry + OFFSET(module_sect_attr_name), + KVADDR, &name, sizeof(void *), + "module_sect_attr.name", RETURN_ON_ERROR|QUIET)) { + done = TRUE; + retval = FALSE; + continue; + } + break; + default: + done = TRUE; + retval = FALSE; + } } if (CRASHDEBUG(2)) {