In some cases, it was able to find a type or location info (for per-cpu variable) but cannot match because of invalid offset or missing global information. In those cases, it's meaningless to go to the outer scope and retry because there will be no additional information. Let's change the return type of find_matching_type() and bail out if it returns -1 for the cases.
Unified · Split
| @@ -1115,10 +1115,15 @@ static void setup_stack_canary(struct data_loc_info *dloc) · 1114 unmodified lines | |||
| 1115 | } | 1115 | } |
| 1116 | } | 1116 | } |
| 1117 | 1117 | ||
| 1118 | /* It's at the target address, check if it has a matching type */ | 1118 | /* |
| 1119 | static bool check_matching_type(struct type_state *state, | 1119 | * It's at the target address, check if it has a matching type. |
| 1120 | struct data_loc_info *dloc, int reg, | 1120 | * It returns 1 if found, 0 if not or -1 if not found but no need to |
| 1121 | Dwarf_Die *cu_die, Dwarf_Die *type_die) | 1121 | * repeat the search. The last case is for per-cpu variables which |
| 1122 | * are similar to global variables and no additional info is needed. | ||
| 1123 | */ | ||
| 1124 | static int check_matching_type(struct type_state *state, | ||
| 1125 | struct data_loc_info *dloc, int reg, | ||
| 1126 | Dwarf_Die *cu_die, Dwarf_Die *type_die) | ||
| 1122 | { | 1127 | { |
| 1123 | Dwarf_Word size; | 1128 | Dwarf_Word size; |
| 1124 | u32 insn_offset = dloc->ip - dloc->ms->sym->start; | 1129 | u32 insn_offset = dloc->ip - dloc->ms->sym->start; |
| @@ -1137,20 +1142,20 @@ static bool check_matching_type(struct type_state *state, · 12 unmodified lines | |||
| 1137 | * dereference a memory location. | 1142 | * dereference a memory location. |
| 1138 | */ | 1143 | */ |
| 1139 | if (tag != DW_TAG_pointer_type && tag != DW_TAG_array_type) | 1144 | if (tag != DW_TAG_pointer_type && tag != DW_TAG_array_type) |
| 1140 | return false; | 1145 | return -1; |
| 1141 | 1146 | ||
| 1142 | /* Remove the pointer and get the target type */ | 1147 | /* Remove the pointer and get the target type */ |
| 1143 | if (die_get_real_type(&state->regs[reg].type, type_die) == NULL) | 1148 | if (die_get_real_type(&state->regs[reg].type, type_die) == NULL) |
| 1144 | return false; | 1149 | return -1; |
| 1145 | 1150 | ||
| 1146 | dloc->type_offset = dloc->op->offset; | 1151 | dloc->type_offset = dloc->op->offset; |
| 1147 | 1152 | ||
| 1148 | /* Get the size of the actual type */ | 1153 | /* Get the size of the actual type */ |
| 1149 | if (dwarf_aggregate_size(type_die, &size) < 0 || | 1154 | if (dwarf_aggregate_size(type_die, &size) < 0 || |
| 1150 | (unsigned)dloc->type_offset >= size) | 1155 | (unsigned)dloc->type_offset >= size) |
| 1151 | return false; | 1156 | return -1; |
| 1152 | 1157 | ||
| 1153 | return true; | 1158 | return 1; |
| 1154 | } | 1159 | } |
| 1155 | 1160 | ||
| 1156 | if (reg == dloc->fbreg) { | 1161 | if (reg == dloc->fbreg) { |
| @@ -1160,18 +1165,18 @@ static bool check_matching_type(struct type_state *state, · 3 unmodified lines | |||
| 1160 | 1165 | ||
| 1161 | stack = find_stack_state(state, dloc->type_offset); | 1166 | stack = find_stack_state(state, dloc->type_offset); |
| 1162 | if (stack == NULL) | 1167 | if (stack == NULL) |
| 1163 | return false; | 1168 | return 0; |
| 1164 | 1169 | ||
| 1165 | if (stack->kind == TSR_KIND_CANARY) { | 1170 | if (stack->kind == TSR_KIND_CANARY) { |
| 1166 | setup_stack_canary(dloc); | 1171 | setup_stack_canary(dloc); |
| 1167 | return false; | 1172 | return -1; |
| 1168 | } | 1173 | } |
| 1169 | 1174 | ||
| 1170 | *type_die = stack->type; | 1175 | *type_die = stack->type; |
| 1171 | /* Update the type offset from the start of slot */ | 1176 | /* Update the type offset from the start of slot */ |
| 1172 | dloc->type_offset -= stack->offset; | 1177 | dloc->type_offset -= stack->offset; |
| 1173 | 1178 | ||
| 1174 | return true; | 1179 | return 1; |
| 1175 | } | 1180 | } |
| 1176 | 1181 | ||
| 1177 | if (dloc->fb_cfa) { | 1182 | if (dloc->fb_cfa) { |
| @@ -1185,22 +1190,22 @@ static bool check_matching_type(struct type_state *state, · 7 unmodified lines | |||
| 1185 | fbreg = -1; | 1190 | fbreg = -1; |
| 1186 | 1191 | ||
| 1187 | if (reg != fbreg) | 1192 | if (reg != fbreg) |
| 1188 | return false; | 1193 | return 0; |
| 1189 | 1194 | ||
| 1190 | stack = find_stack_state(state, dloc->type_offset - fboff); | 1195 | stack = find_stack_state(state, dloc->type_offset - fboff); |
| 1191 | if (stack == NULL) | 1196 | if (stack == NULL) |
| 1192 | return false; | 1197 | return 0; |
| 1193 | 1198 | ||
| 1194 | if (stack->kind == TSR_KIND_CANARY) { | 1199 | if (stack->kind == TSR_KIND_CANARY) { |
| 1195 | setup_stack_canary(dloc); | 1200 | setup_stack_canary(dloc); |
| 1196 | return false; | 1201 | return -1; |
| 1197 | } | 1202 | } |
| 1198 | 1203 | ||
| 1199 | *type_die = stack->type; | 1204 | *type_die = stack->type; |
| 1200 | /* Update the type offset from the start of slot */ | 1205 | /* Update the type offset from the start of slot */ |
| 1201 | dloc->type_offset -= fboff + stack->offset; | 1206 | dloc->type_offset -= fboff + stack->offset; |
| 1202 | 1207 | ||
| 1203 | return true; | 1208 | return 1; |
| 1204 | } | 1209 | } |
| 1205 | 1210 | ||
| 1206 | if (state->regs[reg].kind == TSR_KIND_PERCPU_BASE) { | 1211 | if (state->regs[reg].kind == TSR_KIND_PERCPU_BASE) { |
| @@ -1212,9 +1217,10 @@ static bool check_matching_type(struct type_state *state, · 5 unmodified lines | |||
| 1212 | if (get_global_var_type(cu_die, dloc, dloc->ip, var_addr, | 1217 | if (get_global_var_type(cu_die, dloc, dloc->ip, var_addr, |
| 1213 | &var_offset, type_die)) { | 1218 | &var_offset, type_die)) { |
| 1214 | dloc->type_offset = var_offset; | 1219 | dloc->type_offset = var_offset; |
| 1215 | return true; | 1220 | return 1; |
| 1216 | } | 1221 | } |
| 1217 | return false; | 1222 | /* No need to retry per-cpu (global) variables */ |
| 1223 | return -1; | ||
| 1218 | } | 1224 | } |
| 1219 | 1225 | ||
| 1220 | if (state->regs[reg].ok && state->regs[reg].kind == TSR_KIND_POINTER) { | 1226 | if (state->regs[reg].ok && state->regs[reg].kind == TSR_KIND_POINTER) { |
| @@ -1231,9 +1237,9 @@ static bool check_matching_type(struct type_state *state, · 10 unmodified lines | |||
| 1231 | /* Get the size of the actual type */ | 1237 | /* Get the size of the actual type */ |
| 1232 | if (dwarf_aggregate_size(type_die, &size) < 0 || | 1238 | if (dwarf_aggregate_size(type_die, &size) < 0 || |
| 1233 | (unsigned)dloc->type_offset >= size) | 1239 | (unsigned)dloc->type_offset >= size) |
| 1234 | return false; | 1240 | return -1; |
| 1235 | 1241 | ||
| 1236 | return true; | 1242 | return 1; |
| 1237 | } | 1243 | } |
| 1238 | 1244 | ||
| 1239 | if (state->regs[reg].ok && state->regs[reg].kind == TSR_KIND_CANARY) { | 1245 | if (state->regs[reg].ok && state->regs[reg].kind == TSR_KIND_CANARY) { |
| @@ -1246,7 +1252,7 @@ static bool check_matching_type(struct type_state *state, · 6 unmodified lines | |||
| 1246 | */ | 1252 | */ |
| 1247 | setup_stack_canary(dloc); | 1253 | setup_stack_canary(dloc); |
| 1248 | 1254 | ||
| 1249 | return false; | 1255 | return -1; |
| 1250 | } | 1256 | } |
| 1251 | 1257 | ||
| 1252 | if (map__dso(dloc->ms->map)->kernel && arch__is(dloc->arch, "x86")) { | 1258 | if (map__dso(dloc->ms->map)->kernel && arch__is(dloc->arch, "x86")) { |
| @@ -1262,9 +1268,9 @@ static bool check_matching_type(struct type_state *state, · 9 unmodified lines | |||
| 1262 | if (get_global_var_type(cu_die, dloc, dloc->ip, addr, | 1268 | if (get_global_var_type(cu_die, dloc, dloc->ip, addr, |
| 1263 | &offset, type_die)) { | 1269 | &offset, type_die)) { |
| 1264 | dloc->type_offset = offset; | 1270 | dloc->type_offset = offset; |
| 1265 | return true; | 1271 | return 1; |
| 1266 | } | 1272 | } |
| 1267 | return false; | 1273 | return -1; |
| 1268 | } | 1274 | } |
| 1269 | 1275 | ||
| 1270 | /* Access to per-cpu base like "-0x7dcf0500(,%rdx,8)" */ | 1276 | /* Access to per-cpu base like "-0x7dcf0500(,%rdx,8)" */ |
| @@ -1280,26 +1286,28 @@ static bool check_matching_type(struct type_state *state, · 9 unmodified lines | |||
| 1280 | pr_debug_dtp(" percpu base\n"); | 1286 | pr_debug_dtp(" percpu base\n"); |
| 1281 | 1287 | ||
| 1282 | dloc->type_offset = offset; | 1288 | dloc->type_offset = offset; |
| 1283 | return true; | 1289 | return 1; |
| 1284 | } | 1290 | } |
| 1291 | pr_debug_dtp(" negative offset\n"); | ||
| 1292 | return -1; | ||
| 1285 | } | 1293 | } |
| 1286 | } | 1294 | } |
| 1287 | 1295 | ||
| 1288 | pr_debug_dtp("\n"); | 1296 | pr_debug_dtp("\n"); |
| 1289 | return false; | 1297 | return 0; |
| 1290 | } | 1298 | } |
| 1291 | 1299 | ||
| 1292 | /* Iterate instructions in basic blocks and update type table */ | 1300 | /* Iterate instructions in basic blocks and update type table */ |
| 1293 | static bool find_data_type_insn(struct data_loc_info *dloc, int reg, | 1301 | static int find_data_type_insn(struct data_loc_info *dloc, int reg, |
| 1294 | struct list_head *basic_blocks, | 1302 | struct list_head *basic_blocks, |
| 1295 | struct die_var_type *var_types, | 1303 | struct die_var_type *var_types, |
| 1296 | Dwarf_Die *cu_die, Dwarf_Die *type_die) | 1304 | Dwarf_Die *cu_die, Dwarf_Die *type_die) |
| 1297 | { | 1305 | { |
| 1298 | struct type_state state; | 1306 | struct type_state state; |
| 1299 | struct symbol *sym = dloc->ms->sym; | 1307 | struct symbol *sym = dloc->ms->sym; |
| 1300 | struct annotation *notes = symbol__annotation(sym); | 1308 | struct annotation *notes = symbol__annotation(sym); |
| 1301 | struct annotated_basic_block *bb; | 1309 | struct annotated_basic_block *bb; |
| 1302 | bool found = false; | 1310 | int ret = 0; |
| 1303 | 1311 | ||
| 1304 | init_type_state(&state, dloc->arch); | 1312 | init_type_state(&state, dloc->arch); |
| 1305 | 1313 | ||
| @@ -1317,8 +1325,8 @@ static bool find_data_type_insn(struct data_loc_info *dloc, int reg, · 11 unmodified lines | |||
| 1317 | update_var_state(&state, dloc, addr, dl->al.offset, var_types); | 1325 | update_var_state(&state, dloc, addr, dl->al.offset, var_types); |
| 1318 | 1326 | ||
| 1319 | if (this_ip == dloc->ip) { | 1327 | if (this_ip == dloc->ip) { |
| 1320 | found = check_matching_type(&state, dloc, reg, | 1328 | ret = check_matching_type(&state, dloc, reg, |
| 1321 | cu_die, type_die); | 1329 | cu_die, type_die); |
| 1322 | goto out; | 1330 | goto out; |
| 1323 | } | 1331 | } |
| 1324 | 1332 | ||
| @@ -1331,7 +1339,7 @@ static bool find_data_type_insn(struct data_loc_info *dloc, int reg, · 6 unmodified lines | |||
| 1331 | 1339 | ||
| 1332 | out: | 1340 | out: |
| 1333 | exit_type_state(&state); | 1341 | exit_type_state(&state); |
| 1334 | return found; | 1342 | return ret; |
| 1335 | } | 1343 | } |
| 1336 | 1344 | ||
| 1337 | /* | 1345 | /* |
| @@ -1355,6 +1363,7 @@ static int find_data_type_block(struct data_loc_info *dloc, int reg, · 17 unmodified lines | |||
| 1355 | for (int i = nr_scopes - 1; i >= 0; i--) { | 1363 | for (int i = nr_scopes - 1; i >= 0; i--) { |
| 1356 | Dwarf_Addr base, start, end; | 1364 | Dwarf_Addr base, start, end; |
| 1357 | LIST_HEAD(this_blocks); | 1365 | LIST_HEAD(this_blocks); |
| 1366 | int found; | ||
| 1358 | 1367 | ||
| 1359 | if (dwarf_ranges(&scopes[i], 0, &base, &start, &end) < 0) | 1368 | if (dwarf_ranges(&scopes[i], 0, &base, &start, &end) < 0) |
| 1360 | break; | 1369 | break; |
| @@ -1385,15 +1394,19 @@ again: · 24 unmodified lines | |||
| 1385 | fixup_var_address(var_types, start); | 1394 | fixup_var_address(var_types, start); |
| 1386 | 1395 | ||
| 1387 | /* Find from start of this scope to the target instruction */ | 1396 | /* Find from start of this scope to the target instruction */ |
| 1388 | if (find_data_type_insn(dloc, reg, &basic_blocks, var_types, | 1397 | found = find_data_type_insn(dloc, reg, &basic_blocks, var_types, |
| 1389 | cu_die, type_die)) { | 1398 | cu_die, type_die); |
| 1390 | ret = 0; | 1399 | if (found > 0) { |
| 1391 | pr_debug_dtp("found by insn track: %#x(reg%d) type-offset=%#x", | 1400 | pr_debug_dtp("found by insn track: %#x(reg%d) type-offset=%#x", |
| 1392 | dloc->op->offset, reg, dloc->type_offset); | 1401 | dloc->op->offset, reg, dloc->type_offset); |
| 1393 | pr_debug_type_name(type_die, TSR_KIND_TYPE); | 1402 | pr_debug_type_name(type_die, TSR_KIND_TYPE); |
| 1403 | ret = 0; | ||
| 1394 | break; | 1404 | break; |
| 1395 | } | 1405 | } |
| 1396 | 1406 | ||
| 1407 | if (found < 0) | ||
| 1408 | break; | ||
| 1409 | |||
| 1397 | /* Go up to the next scope and find blocks to the start */ | 1410 | /* Go up to the next scope and find blocks to the start */ |
| 1398 | prev_dst_ip = dst_ip; | 1411 | prev_dst_ip = dst_ip; |
| 1399 | dst_ip = src_ip; | 1412 | dst_ip = src_ip; |