[Ltrace-devel] [PATCH v2] Tracing PLT-less MIPS binaries
Petr Machata
pmachata at redhat.com
Thu Feb 5 23:44:25 UTC 2015
Faraz Shahbazker <faraz.shahbazker at imgtec.com> writes:
> To capture the last one, I've added a check for whether proc->pid occurs
> in options.h:opt_p - not sure if there is a simpler way of performing
> this check.
Both a -p and a command can be given. Probably not something that would
typically be used, but nonetheless this is not a correct way to check
for this.
arch_dylink_done is called either for a process whose execution ltrace
has under control (i.e. initial process or forks of already traced
processes), or always for a process that we attach to. In theory it can
be called even though arch_dylink_ was not, in fact, _done, there's no
deep logic in ltrace to figure out whether the dynamic linker actually
did finish doing its thing.
Which is a shame, but still you could use the callback to make a mark
somewhere and later check it. Or create breakpoins as delayed and only
activate them in the callback--that's what PPC does.
> 2. mips_unresolved_data is shallow copied for each cloned symbol. If a
> child detaches whilst a symbol remains in NEED_UNRESOLVE state, then
> we shouldn't free its unresolve_data because the parent/siblings may
> still need it. I've added a ref_count field to the struct to fix this.
> I am not sure how(if at all) PPC tackles this problem.
Looking in, I don't think it does. That's probably a bug, I'll need to
address that. Good catch!
The refcounting is fine by me, but for ppc I'll just do deep copy.
Easier to get right, I feel.
> + /* Scan LL<->SC range for branches going outside that range */
> + uint32_t spc;
> + for (spc = lladdr + 4; spc < scaddr; spc += 4) {
> + uint32_t scanpcs[2];
> + int snr = mips_next_pcs(proc, spc, scanpcs);
> +
> + if (!inrange(scanpcs[0], lladdr, scaddr)) {
> + if ((newpcs = realloc(newpcs,
> + (nr + 1) * sizeof(spc))) != NULL)
> + newpcs[nr++] = scanpcs[0];
> + }
> +
> + if ((snr == 2) && !inrange(scanpcs[1], lladdr, scaddr)) {
> + if ((newpcs = realloc(newpcs,
> + (nr + 1) * sizeof(spc))) != NULL)
> + newpcs[nr++] = scanpcs[1];
> + }
> + }
Sorry for picking yet more nits, but how about replacing the repetition
in the loop with this?
int i; // actually, ideally unsigned, but you keep it in int
for (i = 0; i < snr; ++i)
if (!inrange(scanpcs[i], lladdr, scaddr))
if ((newpcs = realloc(...)) != NULL)
newpcs[nr++] = scanpcs[i];
Also note that the realloc check is wrong. If the reallocation fails,
you leak, and newpcs becomes NULL. In the next branch, the NULL gets
passed to realloc, which I believe is valid and behaves as if you called
malloc. Thus an error gets muffled and you lose breakpoints. So really
this should be rather something like:
for (i = 0; i < snr; ++i)
if (!inrange(scanpcs[i], lladdr, scaddr)) {
uint32_t *tmp = realloc(newpcs,
(nr + 1) * sizeof(spc));
if (tmp == NULL)
return -1;
/* And have the caller handle -1. */
newpcs = tmp;
newpcs[nr++] = scanpcs[i];
}
And looking into it yet more, that sizeof(spc) seems wrong as well. It
should be sizeof(*newpcs). The fact that they are both uint32_t is of
course no coincidence, but the sizeof should have a clear indication of
the buffer under allocation.
Thanks,
Petr
More information about the Ltrace-devel
mailing list