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

Reply via email to