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