| #!/bin/gawk |
| # |
| # Copyright (c) 2015 Elvira Khabirova <lineprinter0@gmail.com> |
| # Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org> |
| # Copyright (c) 2015-2018 The strace developers. |
| # All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions |
| # are met: |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # 3. The name of the author may not be used to endorse or promote products |
| # derived from this software without specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| function array_get(array_idx, array_member, \ |
| array_return) |
| { |
| array_return = array[array_idx, array_member] |
| if ("" == array_return) { |
| printf("%s: index [%s] without %s\n", |
| FILENAME, array_idx, array_member) > "/dev/stderr" |
| exit 1 |
| } |
| return array_return |
| } |
| function norm_idx(idx) |
| { |
| return sprintf("%016s", idx) |
| } |
| function array_seq(array_idx) |
| { |
| if ((array_idx, "seq") in array) |
| return array[array_idx, "seq"] |
| index_seq++ |
| array[array_idx, "seq"] = index_seq |
| return index_seq |
| } |
| function enter(array_idx, |
| item) |
| { |
| if (array_idx in called) { |
| printf("%s: index loop detected:", FILENAME) > "/dev/stderr" |
| for (item in called) |
| printf(" %s", item) > "/dev/stderr" |
| print "" > "/dev/stderr" |
| exit 1 |
| } |
| called[array_idx] = 1 |
| } |
| function leave(array_idx, to_return) |
| { |
| delete called[array_idx] |
| return to_return |
| } |
| function update_upper_bound(idx, val, \ |
| count) |
| { |
| count = array[idx, "count"] |
| if (count == "") |
| count = 1 |
| array[idx, "count"] = count * val |
| array[idx, "upper_bound"] = array[idx, "upper_bound"] "[" val "]" |
| } |
| function what_is(what_idx, \ |
| item, loc_diff, location, prev_location, prev_returned_size, \ |
| special, to_return, type_idx, enc, i) |
| { |
| enter(what_idx) |
| special = array_get(what_idx, "special") |
| if (special == "base_type") { |
| enc = array_get(what_idx, "encoding") |
| if (enc == 5) { # signed |
| printf("int%s_t ", |
| 8 * array_get(what_idx, "byte_size")) |
| } else if (enc == 7) { # unsigned |
| printf("uint%s_t ", |
| 8 * array_get(what_idx, "byte_size")) |
| } else { # float, signed/unsigned char |
| printf("%s ", array_get(what_idx, "name")) |
| } |
| returned_size = array_get(what_idx, "byte_size") |
| } else if (special == "enumeration_type") { |
| returned_size = array_get(what_idx, "byte_size") |
| printf("uint%s_t ", 8 * returned_size) |
| } else if (special == "pointer_type") { |
| printf("mpers_ptr_t ") |
| returned_size = array_get(what_idx, "byte_size") |
| } else if (special == "array_type") { |
| type_idx = array_get(what_idx, "type") |
| what_is(type_idx) |
| to_return = array[what_idx, "upper_bound"] |
| if ("" == to_return) |
| to_return = "[0]" |
| returned_size = array[what_idx, "count"] * returned_size |
| return leave(what_idx, to_return) |
| } else if (special == "structure_type") { |
| print "struct {" |
| prev_location = 0 |
| location = 0 |
| returned_size = 0 |
| prev_returned_size = 0 |
| for (i = 1; i <= parents_cnt; i += 1) { |
| if (array_parents[aparents_keys[i]] == what_idx) { |
| location = array_get(aparents_keys[i], "location") |
| loc_diff = location - prev_location - \ |
| prev_returned_size |
| if (loc_diff != 0) { |
| printf("unsigned char mpers_%s_%s[%s];\n", |
| "filler", array_seq(aparents_keys[i]), loc_diff) |
| } |
| prev_location = location |
| returned = what_is(aparents_keys[i]) |
| prev_returned_size = returned_size |
| printf("%s%s;\n", array[aparents_keys[i], "name"], returned) |
| } |
| } |
| returned_size = array_get(what_idx, "byte_size") |
| loc_diff = returned_size - prev_location - prev_returned_size |
| if (loc_diff != 0) { |
| printf("unsigned char mpers_%s_%s[%s];\n", |
| "end_filler", array_seq(item), loc_diff) |
| } |
| printf("} ATTRIBUTE_PACKED ") |
| } else if (special == "union_type") { |
| print "union {" |
| for (i = 1; i <= parents_cnt; i += 1) { |
| if (array_parents[aparents_keys[i]] == what_idx) { |
| returned = what_is(aparents_keys[i]) |
| printf("%s%s;\n", array[aparents_keys[i], "name"], returned) |
| } |
| } |
| printf("} ") |
| returned_size = array_get(what_idx, "byte_size") |
| } else if (special == "typedef") { |
| type_idx = array_get(what_idx, "type") |
| return leave(what_idx, what_is(type_idx)) |
| } else if (special == "member") { |
| type_idx = array_get(what_idx, "type") |
| return leave(what_idx, what_is(type_idx)) |
| } else { |
| type_idx = array_get(what_idx, "type") |
| what_is(type_idx) |
| } |
| return leave(what_idx, "") |
| } |
| BEGIN { |
| match(ARCH_FLAG, /[[:digit:]]+/, temparray) |
| default_pointer_size = temparray[0] / 8 |
| print "#include <stdint.h>" |
| } |
| /^<[[:xdigit:]]+>/ { |
| match($0, /([[:alnum:]]+)><([[:alnum:]]+)/, matches) |
| level = matches[1] |
| idx = norm_idx(matches[2]) |
| array[idx, "idx"] = idx |
| parent[level] = idx |
| } |
| /^DW_AT_data_member_location/ { |
| if (!match($0, /\(DW_OP_plus_uconst:[[:space:]]+([[:digit:]]+)\)/, temparray)) |
| match($0, /([[:digit:]]+)/, temparray) |
| array[idx, "location"] = temparray[1] |
| } |
| /^DW_AT_name/ { |
| match($0, /:[[:space:]]+([[:alpha:]_][[:alnum:]_[:space:]]*)/, \ |
| temparray) |
| array_names[idx] = 1 |
| array[idx, "name"] = temparray[1] |
| } |
| /^DW_AT_byte_size/ { |
| match($0, /[[:digit:]]+/, temparray) |
| array[idx, "byte_size"] = temparray[0] |
| } |
| /^DW_AT_encoding/ { |
| match($0, /[[:digit:]]+/, temparray) |
| array[idx, "encoding"] = temparray[0] |
| } |
| /^DW_AT_type/ { |
| match($0, /:[[:space:]]+<0x([[:xdigit:]]*)>$/, temparray) |
| array[idx, "type"] = norm_idx(temparray[1]) |
| } |
| /^DW_AT_upper_bound/ { |
| match($0, /[[:digit:]]+/, temparray) |
| update_upper_bound(parent[level - 1], temparray[0] + 1) |
| } |
| /^DW_AT_count/ { |
| match($0, /[[:digit:]]+/, temparray) |
| update_upper_bound(parent[level - 1], temparray[0]) |
| } |
| /^Abbrev Number:[^(]+\(DW_TAG_/ { |
| if (match($0, /typedef|union_type|structure_type|pointer_type\ |
| |enumeration_type|array_type|base_type|member/, temparray)) { |
| array_special[idx] = temparray[0] |
| array[idx, "special"] = temparray[0] |
| if ("pointer_type" == temparray[0]) |
| array[idx, "byte_size"] = default_pointer_size |
| if (level > 1 && "member" == temparray[0]) |
| array_parents[idx] = parent[level-1] |
| } |
| } |
| END { |
| parents_cnt = asorti(array_parents, aparents_keys) |
| |
| for (item in array_special) { |
| if (array[item, "special"] == "pointer_type") { |
| mpers_ptr_t = \ |
| "uint" 8 * array_get(item, "byte_size") "_t" |
| print "#ifndef mpers_ptr_t_is_" mpers_ptr_t |
| print "typedef " mpers_ptr_t " mpers_ptr_t;" |
| print "#define mpers_ptr_t_is_" mpers_ptr_t |
| print "#endif" |
| break |
| } |
| } |
| for (item in array_names) { |
| if (array[item, "name"] == VAR_NAME) { |
| type = array_get(item, "type") |
| print "typedef" |
| what_is(type) |
| name = array_get(type, "name") |
| print ARCH_FLAG "_" name ";" |
| print "#define MPERS_" \ |
| ARCH_FLAG "_" name " " \ |
| ARCH_FLAG "_" name |
| break |
| } |
| } |
| } |