/*
  * Convert a location into trace_arg.
  * If tvar == NULL, this just checks variable can be converted.
+ * If fentry == true and vr_die is a parameter, do huristic search
+ * for the location fuzzed by function entry mcount.
  */
 static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
-                                    Dwarf_Op *fb_ops,
+                                    Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
                                     struct probe_trace_arg *tvar)
 {
        Dwarf_Attribute attr;
+       Dwarf_Addr tmp = 0;
        Dwarf_Op *op;
        size_t nops;
        unsigned int regn;
                goto static_var;
 
        /* TODO: handle more than 1 exprs */
-       if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL ||
-           dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0 ||
-           nops == 0) {
-               /* TODO: Support const_value */
+       if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
+               return -EINVAL; /* Broken DIE ? */
+       if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) {
+               ret = dwarf_entrypc(sp_die, &tmp);
+               if (ret || addr != tmp ||
+                   dwarf_tag(vr_die) != DW_TAG_formal_parameter ||
+                   dwarf_highpc(sp_die, &tmp))
+                       return -ENOENT;
+               /*
+                * This is fuzzed by fentry mcount. We try to find the
+                * parameter location at the earliest address.
+                */
+               for (addr += 1; addr <= tmp; addr++) {
+                       if (dwarf_getlocation_addr(&attr, addr, &op,
+                                                  &nops, 1) > 0)
+                               goto found;
+               }
                return -ENOENT;
        }
+found:
+       if (nops == 0)
+               /* TODO: Support const_value */
+               return -ENOENT;
 
        if (op->atom == DW_OP_addr) {
 static_var:
                 dwarf_diename(vr_die));
 
        ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
-                                       pf->tvar);
+                                       &pf->sp_die, pf->tvar);
        if (ret == -ENOENT)
                pr_err("Failed to find the location of %s at this address.\n"
                       " Perhaps, it has been optimized out.\n", pf->pvar->var);
 static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
 {
        struct local_vars_finder *vf = data;
+       struct probe_finder *pf = vf->pf;
        int tag;
 
        tag = dwarf_tag(die_mem);
        if (tag == DW_TAG_formal_parameter ||
            tag == DW_TAG_variable) {
                if (convert_variable_location(die_mem, vf->pf->addr,
-                                             vf->pf->fb_ops, NULL) == 0) {
+                                             vf->pf->fb_ops, &pf->sp_die,
+                                             NULL) == 0) {
                        vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
                        if (vf->args[vf->nargs].var == NULL) {
                                vf->ret = -ENOMEM;
        if (tag == DW_TAG_formal_parameter ||
            tag == DW_TAG_variable) {
                ret = convert_variable_location(die_mem, af->pf.addr,
-                                               af->pf.fb_ops, NULL);
+                                               af->pf.fb_ops, &af->pf.sp_die,
+                                               NULL);
                if (ret == 0) {
                        ret = die_get_varname(die_mem, buf, MAX_VAR_LEN);
                        pr_debug2("Add new var: %s\n", buf);