@@ -248,6 +248,7 @@ static void update_insn_state_x86(struct type_state *state,
248248 tsr = & state -> regs [state -> ret_reg ];
249249 tsr -> type = type_die ;
250250 tsr -> kind = TSR_KIND_TYPE ;
251+ tsr -> offset = 0 ;
251252 tsr -> ok = true;
252253
253254 pr_debug_dtp ("call [%x] return -> reg%d" ,
@@ -284,13 +285,27 @@ static void update_insn_state_x86(struct type_state *state,
284285 !strcmp (var_name , "this_cpu_off" ) &&
285286 tsr -> kind == TSR_KIND_CONST ) {
286287 tsr -> kind = TSR_KIND_PERCPU_BASE ;
288+ tsr -> offset = 0 ;
287289 tsr -> ok = true;
288290 imm_value = tsr -> imm_value ;
289291 }
290292 }
291293 else
292294 return ;
293295
296+ /* Ignore add to non-pointer or non-const types */
297+ if (tsr -> kind == TSR_KIND_POINTER ||
298+ (dwarf_tag (& tsr -> type ) == DW_TAG_pointer_type &&
299+ src -> reg1 != DWARF_REG_PC && tsr -> kind == TSR_KIND_TYPE && !dst -> mem_ref )) {
300+ tsr -> offset += imm_value ;
301+ pr_debug_dtp ("add [%x] offset %#" PRIx64 " to reg%d" ,
302+ insn_offset , imm_value , dst -> reg1 );
303+ pr_debug_type_name (& tsr -> type , tsr -> kind );
304+ }
305+
306+ if (tsr -> kind == TSR_KIND_CONST )
307+ tsr -> imm_value += imm_value ;
308+
294309 if (tsr -> kind != TSR_KIND_PERCPU_BASE )
295310 return ;
296311
@@ -302,6 +317,7 @@ static void update_insn_state_x86(struct type_state *state,
302317 */
303318 tsr -> type = type_die ;
304319 tsr -> kind = TSR_KIND_PERCPU_POINTER ;
320+ tsr -> offset = 0 ;
305321 tsr -> ok = true;
306322
307323 pr_debug_dtp ("add [%x] percpu %#" PRIx64 " -> reg%d" ,
@@ -311,6 +327,106 @@ static void update_insn_state_x86(struct type_state *state,
311327 return ;
312328 }
313329
330+ if (!strncmp (dl -> ins .name , "sub" , 3 )) {
331+ u64 imm_value = -1ULL ;
332+
333+ if (!has_reg_type (state , dst -> reg1 ))
334+ return ;
335+
336+ tsr = & state -> regs [dst -> reg1 ];
337+ tsr -> copied_from = -1 ;
338+
339+ if (src -> imm )
340+ imm_value = src -> offset ;
341+ else if (has_reg_type (state , src -> reg1 ) &&
342+ state -> regs [src -> reg1 ].kind == TSR_KIND_CONST )
343+ imm_value = state -> regs [src -> reg1 ].imm_value ;
344+
345+ if (tsr -> kind == TSR_KIND_POINTER ||
346+ (dwarf_tag (& tsr -> type ) == DW_TAG_pointer_type &&
347+ src -> reg1 != DWARF_REG_PC && tsr -> kind == TSR_KIND_TYPE && !dst -> mem_ref )) {
348+ tsr -> offset -= imm_value ;
349+ pr_debug_dtp ("sub [%x] offset %#" PRIx64 " to reg%d" ,
350+ insn_offset , imm_value , dst -> reg1 );
351+ pr_debug_type_name (& tsr -> type , tsr -> kind );
352+ }
353+
354+ if (tsr -> kind == TSR_KIND_CONST )
355+ tsr -> imm_value -= imm_value ;
356+
357+ return ;
358+ }
359+
360+ if (!strncmp (dl -> ins .name , "lea" , 3 )) {
361+ int sreg = src -> reg1 ;
362+ struct type_state_reg src_tsr ;
363+
364+ if (!has_reg_type (state , sreg ) ||
365+ !has_reg_type (state , dst -> reg1 ) ||
366+ !src -> mem_ref )
367+ return ;
368+
369+ src_tsr = state -> regs [sreg ];
370+ tsr = & state -> regs [dst -> reg1 ];
371+
372+ tsr -> copied_from = -1 ;
373+ tsr -> ok = false;
374+
375+ /* Case 1: Based on stack pointer or frame pointer */
376+ if (sreg == fbreg || sreg == state -> stack_reg ) {
377+ struct type_state_stack * stack ;
378+ int offset = src -> offset - fboff ;
379+
380+ stack = find_stack_state (state , offset );
381+ if (!stack )
382+ return ;
383+
384+ tsr -> type = stack -> type ;
385+ tsr -> kind = TSR_KIND_POINTER ;
386+ tsr -> offset = offset - stack -> offset ;
387+ tsr -> ok = true;
388+
389+ if (sreg == fbreg ) {
390+ pr_debug_dtp ("lea [%x] address of -%#x(stack) -> reg%d" ,
391+ insn_offset , - src -> offset , dst -> reg1 );
392+ } else {
393+ pr_debug_dtp ("lea [%x] address of %#x(reg%d) -> reg%d" ,
394+ insn_offset , src -> offset , sreg , dst -> reg1 );
395+ }
396+
397+ pr_debug_type_name (& tsr -> type , tsr -> kind );
398+ }
399+ /* Case 2: Based on a register holding a typed pointer */
400+ else if (src_tsr .ok && (src_tsr .kind == TSR_KIND_POINTER ||
401+ (dwarf_tag (& src_tsr .type ) == DW_TAG_pointer_type &&
402+ src_tsr .kind == TSR_KIND_TYPE ))) {
403+
404+ if (src_tsr .kind == TSR_KIND_TYPE &&
405+ __die_get_real_type (& state -> regs [sreg ].type , & type_die ) == NULL )
406+ return ;
407+
408+ if (src_tsr .kind == TSR_KIND_POINTER )
409+ type_die = state -> regs [sreg ].type ;
410+
411+ /* Check if the target type has a member at the new offset */
412+ if (die_get_member_type (& type_die ,
413+ src -> offset + src_tsr .offset , & type_die ) == NULL )
414+ return ;
415+
416+ tsr -> type = src_tsr .type ;
417+ tsr -> kind = src_tsr .kind ;
418+ tsr -> offset = src -> offset + src_tsr .offset ;
419+ tsr -> ok = true;
420+
421+ pr_debug_dtp ("lea [%x] address of %s%#x(reg%d) -> reg%d" ,
422+ insn_offset , src -> offset < 0 ? "-" : "" ,
423+ abs (src -> offset ), sreg , dst -> reg1 );
424+
425+ pr_debug_type_name (& tsr -> type , tsr -> kind );
426+ }
427+ return ;
428+ }
429+
314430 if (strncmp (dl -> ins .name , "mov" , 3 ))
315431 return ;
316432
@@ -345,6 +461,7 @@ static void update_insn_state_x86(struct type_state *state,
345461
346462 if (var_addr == 40 ) {
347463 tsr -> kind = TSR_KIND_CANARY ;
464+ tsr -> offset = 0 ;
348465 tsr -> ok = true;
349466
350467 pr_debug_dtp ("mov [%x] stack canary -> reg%d\n" ,
@@ -361,6 +478,7 @@ static void update_insn_state_x86(struct type_state *state,
361478
362479 tsr -> type = type_die ;
363480 tsr -> kind = TSR_KIND_TYPE ;
481+ tsr -> offset = 0 ;
364482 tsr -> ok = true;
365483
366484 pr_debug_dtp ("mov [%x] this-cpu addr=%#" PRIx64 " -> reg%d" ,
@@ -372,6 +490,7 @@ static void update_insn_state_x86(struct type_state *state,
372490 if (src -> imm ) {
373491 tsr -> kind = TSR_KIND_CONST ;
374492 tsr -> imm_value = src -> offset ;
493+ tsr -> offset = 0 ;
375494 tsr -> ok = true;
376495
377496 pr_debug_dtp ("mov [%x] imm=%#x -> reg%d\n" ,
@@ -388,6 +507,7 @@ static void update_insn_state_x86(struct type_state *state,
388507 tsr -> type = state -> regs [src -> reg1 ].type ;
389508 tsr -> kind = state -> regs [src -> reg1 ].kind ;
390509 tsr -> imm_value = state -> regs [src -> reg1 ].imm_value ;
510+ tsr -> offset = state -> regs [src -> reg1 ].offset ;
391511 tsr -> ok = true;
392512
393513 /* To copy back the variable type later (hopefully) */
@@ -421,12 +541,14 @@ static void update_insn_state_x86(struct type_state *state,
421541 } else if (!stack -> compound ) {
422542 tsr -> type = stack -> type ;
423543 tsr -> kind = stack -> kind ;
544+ tsr -> offset = 0 ;
424545 tsr -> ok = true;
425546 } else if (die_get_member_type (& stack -> type ,
426547 offset - stack -> offset ,
427548 & type_die )) {
428549 tsr -> type = type_die ;
429550 tsr -> kind = TSR_KIND_TYPE ;
551+ tsr -> offset = 0 ;
430552 tsr -> ok = true;
431553 } else {
432554 tsr -> ok = false;
@@ -446,9 +568,10 @@ static void update_insn_state_x86(struct type_state *state,
446568 else if (has_reg_type (state , sreg ) && state -> regs [sreg ].ok &&
447569 state -> regs [sreg ].kind == TSR_KIND_TYPE &&
448570 die_deref_ptr_type (& state -> regs [sreg ].type ,
449- src -> offset , & type_die )) {
571+ src -> offset + state -> regs [ sreg ]. offset , & type_die )) {
450572 tsr -> type = type_die ;
451573 tsr -> kind = TSR_KIND_TYPE ;
574+ tsr -> offset = 0 ;
452575 tsr -> ok = true;
453576
454577 pr_debug_dtp ("mov [%x] %#x(reg%d) -> reg%d" ,
@@ -459,9 +582,10 @@ static void update_insn_state_x86(struct type_state *state,
459582 else if (has_reg_type (state , sreg ) && state -> regs [sreg ].ok &&
460583 state -> regs [sreg ].kind == TSR_KIND_POINTER &&
461584 die_get_member_type (& state -> regs [sreg ].type ,
462- src -> offset , & type_die )) {
585+ src -> offset + state -> regs [ sreg ]. offset , & type_die )) {
463586 tsr -> type = state -> regs [sreg ].type ;
464587 tsr -> kind = TSR_KIND_TYPE ;
588+ tsr -> offset = src -> offset + state -> regs [sreg ].offset ;
465589 tsr -> ok = true;
466590
467591 pr_debug_dtp ("mov [%x] addr %#x(reg%d) -> reg%d" ,
@@ -486,6 +610,7 @@ static void update_insn_state_x86(struct type_state *state,
486610
487611 tsr -> type = type_die ;
488612 tsr -> kind = TSR_KIND_TYPE ;
613+ tsr -> offset = 0 ;
489614 tsr -> ok = true;
490615
491616 pr_debug_dtp ("mov [%x] global addr=%" PRIx64 " -> reg%d" ,
@@ -517,6 +642,7 @@ static void update_insn_state_x86(struct type_state *state,
517642 die_get_member_type (& type_die , offset , & type_die )) {
518643 tsr -> type = type_die ;
519644 tsr -> kind = TSR_KIND_TYPE ;
645+ tsr -> offset = 0 ;
520646 tsr -> ok = true;
521647
522648 if (src -> multi_regs ) {
@@ -539,6 +665,7 @@ static void update_insn_state_x86(struct type_state *state,
539665 src -> offset , & type_die )) {
540666 tsr -> type = type_die ;
541667 tsr -> kind = TSR_KIND_TYPE ;
668+ tsr -> offset = 0 ;
542669 tsr -> ok = true;
543670
544671 pr_debug_dtp ("mov [%x] pointer %#x(reg%d) -> reg%d" ,
@@ -561,6 +688,7 @@ static void update_insn_state_x86(struct type_state *state,
561688 & var_name , & offset ) &&
562689 !strcmp (var_name , "__per_cpu_offset" )) {
563690 tsr -> kind = TSR_KIND_PERCPU_BASE ;
691+ tsr -> offset = 0 ;
564692 tsr -> ok = true;
565693
566694 pr_debug_dtp ("mov [%x] percpu base reg%d\n" ,
@@ -609,6 +737,11 @@ static void update_insn_state_x86(struct type_state *state,
609737 pr_debug_dtp ("mov [%x] reg%d -> %#x(reg%d)" ,
610738 insn_offset , src -> reg1 , offset , dst -> reg1 );
611739 }
740+ if (tsr -> offset != 0 ) {
741+ pr_debug_dtp (" reg%d offset %#x ->" ,
742+ src -> reg1 , tsr -> offset );
743+ }
744+
612745 pr_debug_type_name (& tsr -> type , tsr -> kind );
613746 }
614747 /*
0 commit comments