Home | History | Annotate | Download | only in strace
      1 #!/bin/gawk
      2 #
      3 # Copyright (c) 2015 Elvira Khabirova <lineprinter0 (at] gmail.com>
      4 # Copyright (c) 2015-2016 Dmitry V. Levin <ldv (at] altlinux.org>
      5 # Copyright (c) 2015-2017 The strace developers.
      6 # All rights reserved.
      7 #
      8 # Redistribution and use in source and binary forms, with or without
      9 # modification, are permitted provided that the following conditions
     10 # are met:
     11 # 1. Redistributions of source code must retain the above copyright
     12 #    notice, this list of conditions and the following disclaimer.
     13 # 2. Redistributions in binary form must reproduce the above copyright
     14 #    notice, this list of conditions and the following disclaimer in the
     15 #    documentation and/or other materials provided with the distribution.
     16 # 3. The name of the author may not be used to endorse or promote products
     17 #    derived from this software without specific prior written permission.
     18 #
     19 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 function compare_indices(i1, v1, i2, v2) {
     31 	c1 = strtonum(sprintf("%s", i1))
     32 	c2 = strtonum(sprintf("%s", i2))
     33 	if (c1 < c2)
     34 		return -1
     35 	return (c1 != c2)
     36 }
     37 function array_get(array_idx, array_member, array_return)
     38 {
     39 	array_return = array[array_idx][array_member]
     40 	if ("" == array_return) {
     41 		printf("%s: index [%s] without %s\n",
     42 		       FILENAME, array_idx, array_member) > "/dev/stderr"
     43 		exit 1
     44 	}
     45 	return array_return
     46 }
     47 function array_seq(array_idx)
     48 {
     49 	if ("seq" in array[array_idx])
     50 		return array[array_idx]["seq"]
     51 	index_seq++
     52 	array[array_idx]["seq"] = index_seq
     53 	return index_seq
     54 }
     55 function enter(array_idx)
     56 {
     57 	if (array_idx in called) {
     58 		printf("%s: index loop detected:", FILENAME) > "/dev/stderr"
     59 		for (item in called)
     60 			printf(" %s", item) > "/dev/stderr"
     61 		print "" > "/dev/stderr"
     62 		exit 1
     63 	}
     64 	called[array_idx] = 1
     65 }
     66 function leave(array_idx, to_return)
     67 {
     68 	delete called[array_idx]
     69 	return to_return
     70 }
     71 function update_upper_bound(idx, val, count)
     72 {
     73 	count = array[idx]["count"]
     74 	if (count == "")
     75 		count = 1
     76 	array[idx]["count"] = count * val
     77 	array[idx]["upper_bound"] = array[idx]["upper_bound"] "[" val "]"
     78 }
     79 function what_is(what_idx, type_idx, special, item, \
     80 		 location, prev_location, prev_returned_size)
     81 {
     82 	enter(what_idx)
     83 	special = array_get(what_idx, "special")
     84 	switch (special) {
     85 	case "base_type":
     86 		switch (array_get(what_idx, "encoding")) {
     87 		case 5: # signed
     88 			printf("int%s_t ",
     89 			       8 * array_get(what_idx, "byte_size"))
     90 			break
     91 		case 7: # unsigned
     92 			printf("uint%s_t ",
     93 			       8 * array_get(what_idx, "byte_size"))
     94 			break
     95 		default: # float, signed/unsigned char
     96 			printf("%s ", array_get(what_idx, "name"))
     97 			break
     98 		}
     99 		returned_size = array_get(what_idx, "byte_size")
    100 		break
    101 	case "enumeration_type":
    102 		returned_size = array_get(what_idx, "byte_size")
    103 		printf("uint%s_t ", 8 * returned_size)
    104 		break
    105 	case "pointer_type":
    106 		printf("mpers_ptr_t ")
    107 		returned_size = array_get(what_idx, "byte_size")
    108 		break
    109 	case "array_type":
    110 		type_idx = array_get(what_idx, "type")
    111 		what_is(type_idx)
    112 		to_return = array[what_idx]["upper_bound"]
    113 		if ("" == to_return)
    114 			to_return = "[0]"
    115 		returned_size = array[what_idx]["count"] * returned_size
    116 		return leave(what_idx, to_return)
    117 		break
    118 	case "structure_type":
    119 		print "struct {"
    120 		prev_location = 0
    121 		location = 0
    122 		returned_size = 0
    123 		prev_returned_size = 0
    124 		for (item in array) {
    125 			if ("parent" in array[item] && \
    126 				array_get(item, "parent") == what_idx) {
    127 				location = array_get(item, "location")
    128 				loc_diff = location - prev_location - \
    129 					prev_returned_size
    130 				if (loc_diff != 0) {
    131 					printf("unsigned char mpers_%s_%s[%s];\n",
    132 					       "filler", array_seq(item), loc_diff)
    133 				}
    134 				prev_location = location
    135 				returned = what_is(item)
    136 				prev_returned_size = returned_size
    137 				printf("%s%s;\n", array[item]["name"], returned)
    138 			}
    139 		}
    140 		returned_size = array_get(what_idx, "byte_size")
    141 		loc_diff = returned_size - prev_location - prev_returned_size
    142 		if (loc_diff != 0) {
    143 			printf("unsigned char mpers_%s_%s[%s];\n",
    144 			       "end_filler", array_seq(item), loc_diff)
    145 		}
    146 		printf("} ATTRIBUTE_PACKED ")
    147 		break
    148 	case "union_type":
    149 		print "union {"
    150 		for (item in array) {
    151 			if ("parent" in array[item] && \
    152 				array_get(item, "parent") == what_idx) {
    153 				returned = what_is(item)
    154 				printf("%s%s;\n", array[item]["name"], returned)
    155 			}
    156 		}
    157 		printf("} ")
    158 		returned_size = array_get(what_idx, "byte_size")
    159 		break
    160 	case "typedef":
    161 		type_idx = array_get(what_idx, "type")
    162 		return leave(what_idx, what_is(type_idx))
    163 		break
    164 	case "member":
    165 		type_idx = array_get(what_idx, "type")
    166 		return leave(what_idx, what_is(type_idx))
    167 		break
    168 	default:
    169 		type_idx = array_get(what_idx, "type")
    170 		what_is(type_idx)
    171 		break
    172 	}
    173 	return leave(what_idx, "")
    174 }
    175 BEGIN {
    176 	match(ARCH_FLAG, /[[:digit:]]+/, temparray)
    177 	default_pointer_size = temparray[0] / 8
    178 	print "#include <inttypes.h>"
    179 }
    180 /^<[[:xdigit:]]+>/ {
    181 	match($0, /([[:alnum:]]+)><([[:alnum:]]+)/, matches)
    182 	level = matches[1]
    183 	idx = "0x" matches[2]
    184 	array[idx]["idx"] = idx
    185 	parent[level] = idx
    186 }
    187 /^DW_AT_data_member_location/ {
    188 	if (!match($0, /\(DW_OP_plus_uconst:[[:space:]]+([[:digit:]]+)\)/, temparray))
    189 		match($0, /([[:digit:]]+)/, temparray)
    190 	array[idx]["location"] = temparray[1]
    191 }
    192 /^DW_AT_name/ {
    193 	match($0, /:[[:space:]]+([[:alpha:]_][[:alnum:]_[:space:]]*)/, \
    194 		temparray)
    195 	array[idx]["name"] = temparray[1]
    196 }
    197 /^DW_AT_byte_size/ {
    198 	match($0, /[[:digit:]]+/, temparray)
    199 	array[idx]["byte_size"] = temparray[0]
    200 }
    201 /^DW_AT_encoding/ {
    202 	match($0, /[[:digit:]]+/, temparray)
    203 	array[idx]["encoding"] = temparray[0]
    204 }
    205 /^DW_AT_type/ {
    206 	match($0, /:[[:space:]]+<(0x[[:xdigit:]]*)>$/, temparray)
    207 	array[idx]["type"] = temparray[1]
    208 }
    209 /^DW_AT_upper_bound/ {
    210 	match($0, /[[:digit:]]+/, temparray)
    211 	update_upper_bound(parent[level - 1], temparray[0] + 1)
    212 }
    213 /^DW_AT_count/ {
    214 	match($0, /[[:digit:]]+/, temparray)
    215 	update_upper_bound(parent[level - 1], temparray[0])
    216 }
    217 /^Abbrev Number:[^(]+\(DW_TAG_/ {
    218 	if (match($0, /typedef|union_type|structure_type|pointer_type\
    219 |enumeration_type|array_type|base_type|member/, temparray)) {
    220 		array[idx]["special"] = temparray[0]
    221 		if ("pointer_type" == temparray[0])
    222 			array[idx]["byte_size"] = default_pointer_size
    223 		if (level > 1 && "member" == temparray[0])
    224 			array[idx]["parent"] = parent[level-1]
    225 	}
    226 }
    227 END {
    228 	PROCINFO["sorted_in"] = "compare_indices"
    229 	for (item in array) {
    230 		if (array[item]["special"] == "pointer_type") {
    231 			print "typedef uint" \
    232 				8 * array_get(item, "byte_size") "_t mpers_ptr_t;"
    233 			break
    234 		}
    235 	}
    236 	for (item in array) {
    237 		if (array[item]["name"] == VAR_NAME) {
    238 			type = array_get(item, "type")
    239 			print "typedef"
    240 			what_is(type)
    241 			name = array_get(type, "name")
    242 			print ARCH_FLAG "_" name ";"
    243 			print "#define MPERS_" \
    244 				ARCH_FLAG "_" name " " \
    245 				ARCH_FLAG "_" name
    246 			break
    247 		}
    248 	}
    249 }
    250