Hi.
This patch adds get_array_length() for getting the MAX_ORDER value
dynamically. The MAX_ORDER value is the number of the array
"zone.free_area[]" that depends on CONFIG_FORCE_MAX_ZONEORDER,
and it is included in the debug information of the kernel file.
makedumpfile gets it by analyzing the debug information.
Thanks
Ken'ichi Ohmichi
diff -puN makedumpfile.org/makedumpfile.c makedumpfile/makedumpfile.c
--- makedumpfile.org/makedumpfile.c 2006-12-07 17:03:00.000000000 +0900
+++ makedumpfile/makedumpfile.c 2006-12-07 17:15:52.000000000 +0900
@@ -25,6 +25,7 @@
struct symbol_table symbol_table;
struct size_table size_table;
struct offset_table offset_table;
+struct array_table array_table;
struct dwarf_info dwarf_info;
struct vm_table *vt = 0;
@@ -853,8 +854,59 @@ get_data_member_location(Dwarf_Die *die)
return TRUE;
}
+static int
+get_data_array_length(Dwarf *dwarfd, Dwarf_Die *die)
+{
+ int tag;
+ Dwarf_Attribute attr;
+ Dwarf_Off offset_type;
+ Dwarf_Die die_type;
+
+ /*
+ * Get the offset of DW_AT_type
+ */
+ if (dwarf_attr(die, DW_AT_type, &attr) == NULL)
+ return FALSE;
+
+ if (dwarf_formref(&attr, &offset_type) < 0)
+ return FALSE;
+
+ if (dwarf_offdie(dwarfd, offset_type, &die_type) == NULL) {
+ ERRMSG("Can't get CU die.\n");
+ return FALSE;
+ }
+
+ tag = dwarf_tag(&die_type);
+ if (tag != DW_TAG_array_type) {
+ /*
+ * This kernel doesn't have the member of array.
+ */
+ return TRUE;
+ }
+
+ /*
+ * Get the demanded array length.
+ */
+ dwarf_child(&die_type, &die_type);
+ do {
+ tag = dwarf_tag(&die_type);
+ if (tag == DW_TAG_subrange_type)
+ break;
+ } while (dwarf_siblingof(&die_type, &die_type));
+
+ if (tag != DW_TAG_subrange_type)
+ return FALSE;
+
+ if (dwarf_attr(&die_type, DW_AT_upper_bound, &attr) == NULL)
+ return FALSE;
+
+ dwarf_info.array_length = (long)(*attr.valp) + 1;
+
+ return TRUE;
+}
+
static void
-process_children(Dwarf_Die *die)
+process_children(Dwarf *dwarfd, Dwarf_Die *die)
{
int tag;
const char *name;
@@ -891,6 +943,15 @@ process_children(Dwarf_Die *die)
if (!get_data_member_location(walker))
continue;
return;
+ case DWARF_INFO_GET_ARRAY_LENGTH:
+ if ((!name) || strcmp(name, dwarf_info.member_name))
+ continue;
+ /*
+ * Get the member length.
+ */
+ if (!get_data_array_length(dwarfd, walker))
+ continue;
+ return;
}
} while (!dwarf_siblingof(walker, walker));
@@ -952,7 +1013,8 @@ search_die_tree(Dwarf *dwarfd, Dwarf_Die
break;
case DWARF_INFO_GET_MEMBER_OFFSET:
case DWARF_INFO_GET_NOT_NAMED_UNION_OFFSET:
- process_children(die);
+ case DWARF_INFO_GET_ARRAY_LENGTH:
+ process_children(dwarfd, die);
break;
}
}
@@ -1066,6 +1128,25 @@ get_member_offset(char *structname, char
return dwarf_info.member_offset;
}
+/*
+ * Get the length of member.
+ */
+long
+get_array_length(char *structname, char *membername)
+{
+ dwarf_info.cmd = DWARF_INFO_GET_ARRAY_LENGTH;
+ dwarf_info.struct_name = structname;
+ dwarf_info.struct_size = NOT_FOUND_STRUCTURE;
+ dwarf_info.member_name = membername;
+ dwarf_info.member_offset = NOT_FOUND_STRUCTURE;
+ dwarf_info.array_length = NOT_FOUND_ARRAY;
+
+ if (!get_debug_info())
+ return FAILED_DWARFINFO;
+
+ return dwarf_info.array_length;
+}
+
int
get_structure_info(struct DumpInfo *info)
{
@@ -1104,6 +1185,7 @@ get_structure_info(struct DumpInfo *info
OFFSET_INIT(zone.free_pages, "zone", "free_pages");
OFFSET_INIT(zone.free_area, "zone", "free_area");
OFFSET_INIT(zone.spanned_pages, "zone", "spanned_pages");
+ ARRAY_LENGTH_INIT(zone.free_area, "zone", "free_area");
/*
* Get offsets of the free_area's members.
@@ -1242,6 +1324,8 @@ generate_config(struct DumpInfo *info)
WRITE_MEMBER_OFFSET("list_head.next", list_head.next);
WRITE_MEMBER_OFFSET("list_head.prev", list_head.prev);
+ WRITE_ARRAY_LENGTH("zone.free_area", zone.free_area);
+
return TRUE;
}
@@ -1391,6 +1475,8 @@ read_config(struct DumpInfo *info)
READ_MEMBER_OFFSET("list_head.next", list_head.next);
READ_MEMBER_OFFSET("list_head.prev", list_head.prev);
+ READ_ARRAY_LENGTH("zone.free_area", zone.free_area);
+
return TRUE;
}
@@ -1919,7 +2005,7 @@ reset_bitmap_of_free_pages(struct DumpIn
unsigned long curr, previous, head, curr_page, curr_prev, free_pages;
unsigned long long pfn, start_pfn;
- for (order = MAX_ORDER - 1; order >= 0; --order) {
+ for (order = (ARRAY_LENGTH(zone.free_area) - 1); order >= 0; --order) {
head = node_zones + OFFSET(zone.free_area)
+ SIZE(free_area) * order + OFFSET(free_area.free_list);
previous = head;
@@ -2042,13 +2128,6 @@ _exclude_free_page(struct DumpInfo *info
} else {
vt->numnodes = 1;
}
- /*
- * FIXME
- * Array length of zone.free_area must be dynamically got
- * each architecture or each config.
- */
- vt->nr_free_areas = MAX_ORDER;
-
if (!dump_memory_nodes(info))
return FALSE;
return TRUE;
@@ -2105,7 +2184,8 @@ exclude_free_page(struct DumpInfo *info,
|| (OFFSET(free_area.free_list) == NOT_FOUND_STRUCTURE)
|| (OFFSET(list_head.next) == NOT_FOUND_STRUCTURE)
|| (OFFSET(list_head.prev) == NOT_FOUND_STRUCTURE)
- || (OFFSET(page.lru) == NOT_FOUND_STRUCTURE)) {
+ || (OFFSET(page.lru) == NOT_FOUND_STRUCTURE)
+ || (ARRAY_LENGTH(zone.free_area) == NOT_FOUND_ARRAY)) {
ERRMSG("Can't get necessary structures for excluding free
pages.\n");
return FALSE;
}
diff -puN makedumpfile.org/makedumpfile.h makedumpfile/makedumpfile.h
--- makedumpfile.org/makedumpfile.h 2006-12-07 17:03:00.000000000 +0900
+++ makedumpfile/makedumpfile.h 2006-12-07 17:18:02.000000000 +0900
@@ -184,8 +184,11 @@ do { \
#define NOT_FOUND_STRUCTURE (-1)
#define FAILED_DWARFINFO (-2)
#define INVALID_STRUCTURE_DATA (-3)
+#define NOT_FOUND_ARRAY (-4)
+
#define SIZE(X) (size_table.X)
#define OFFSET(X) (offset_table.X)
+#define ARRAY_LENGTH(X) (array_table.X)
#define GET_STRUCTURE_SIZE get_structure_size
#define GET_MEMBER_OFFSET get_member_offset
#define SIZE_INIT(X, Y) \
@@ -205,6 +208,12 @@ do { \
== FAILED_DWARFINFO) \
return FALSE; \
} while (0)
+#define ARRAY_LENGTH_INIT(X, Y, Z) \
+do { \
+ if ((ARRAY_LENGTH(X) = get_array_length(Y, Z)) == FAILED_DWARFINFO) \
+ return FALSE; \
+} while (0)
+
#define WRITE_STRUCTURE_SIZE(str_structure, structure) \
do { \
if (SIZE(structure) != NOT_FOUND_STRUCTURE) { \
@@ -219,6 +228,13 @@ do { \
STR_OFFSET(str_member), OFFSET(member)); \
} \
} while (0)
+#define WRITE_ARRAY_LENGTH(str_array, array) \
+do { \
+ if (ARRAY_LENGTH(array) != NOT_FOUND_ARRAY) { \
+ fprintf(info->file_configfile, "%s%ld\n", \
+ STR_LENGTH(str_array), ARRAY_LENGTH(array)); \
+ } \
+} while (0)
#define READ_STRUCTURE_SIZE(str_structure, structure) \
do { \
SIZE(structure) = read_config_structure(info,STR_SIZE(str_structure)); \
@@ -231,6 +247,12 @@ do { \
if (OFFSET(member) == INVALID_STRUCTURE_DATA) \
return FALSE; \
} while (0)
+#define READ_ARRAY_LENGTH(str_array, array) \
+do { \
+ ARRAY_LENGTH(array) = read_config_structure(info,
STR_LENGTH(str_array)); \
+ if (ARRAY_LENGTH(array) == INVALID_STRUCTURE_DATA) \
+ return FALSE; \
+} while (0)
/*
* kernel version
@@ -248,6 +270,7 @@ do { \
#define STR_SYMBOL(X) "SYMBOL("X")="
#define STR_SIZE(X) "SIZE("X")="
#define STR_OFFSET(X) "OFFSET("X")="
+#define STR_LENGTH(X) "LENGTH("X")="
/*
* vm_table
@@ -278,7 +301,6 @@ do { \
#define _SECTION_SIZE_BITS (26)
#define _SECTION_SIZE_BITS_PAE (30)
#define SIZEOF_NODE_ONLINE_MAP (4)
-#define MAX_ORDER (11)
#endif /* x86 */
#ifdef __x86_64__
@@ -291,7 +313,6 @@ do { \
#define KVBASE PAGE_OFFSET
#define _SECTION_SIZE_BITS (27)
#define SIZEOF_NODE_ONLINE_MAP (8)
-#define MAX_ORDER (11)
#endif /* x86_64 */
#ifdef __powerpc__
@@ -301,7 +322,6 @@ do { \
#define KVBASE (SYMBOL(_stext))
#define _SECTION_SIZE_BITS (24)
#define SIZEOF_NODE_ONLINE_MAP (8)
-#define MAX_ORDER (9)
#endif
#ifdef __ia64__ /* ia64 */
@@ -327,7 +347,6 @@ do { \
#define DEFAULT_PHYS_START (KERNEL_TR_PAGE_SIZE * 1)
#define _SECTION_SIZE_BITS (30)
#define SIZEOF_NODE_ONLINE_MAP (32)
-#define MAX_ORDER (17)
#endif /* ia64 */
/*
@@ -467,7 +486,6 @@ struct DumpInfo {
struct vm_table { /* kernel VM-related data */
ulong flags;
int numnodes;
- int nr_free_areas;
ulong *node_online_map;
int node_online_map_len;
} vm_table;
@@ -530,9 +548,19 @@ struct offset_table {
} list_head;
};
+/*
+ * The number of array
+ */
+struct array_table {
+ struct zone_at {
+ long free_area;
+ } zone;
+};
+
extern struct symbol_table symbol_table;
extern struct size_table size_table;
extern struct offset_table offset_table;
+extern struct array_table array_table;
/*
* Debugging information
@@ -540,6 +568,7 @@ extern struct offset_table offset_table;
#define DWARF_INFO_GET_STRUCT_SIZE 1
#define DWARF_INFO_GET_MEMBER_OFFSET 2
#define DWARF_INFO_GET_NOT_NAMED_UNION_OFFSET 3
+#define DWARF_INFO_GET_ARRAY_LENGTH 4
struct dwarf_info {
unsigned int cmd; /* IN */
@@ -549,6 +578,7 @@ struct dwarf_info {
int struct_size; /* OUT */
char *member_name; /* IN */
int member_offset; /* OUT */
+ int array_length; /* OUT */
};
struct dwarf_values {
_
_______________________________________________
fastboot mailing list
[email protected]
https://lists.osdl.org/mailman/listinfo/fastboot