Debugging C pointers on 64 bit
Giorgos Keramidas
keramida at ceid.upatras.gr
Thu Dec 2 16:03:43 EET 2010
On Thu, 02 Dec 2010 12:36:01 +0200, Antonis Christofides <anthony at itia.ntua.gr> wrote:
> Έχω μια shared library γραμμένη σε C, η οποία χρησιμοποιείται από μια
> εφαρμογή Python/Django. Είχε ένα bug με αποτέλεσμα, όταν έτρεχε σε
> σύστημα 64 bit, να χάνει κάποια στιγμή τα άνω 32 bit.
Short story...
------------------------------------------------------------------------
Ψάξε για warnings σχετικά με missing realloc/calloc/malloc() prototypes!
------------------------------------------------------------------------
Long(-ish) story...
Αυτό γίνεται συνήθως όταν ένα πρόγραμμα χρησιμοποιεί casting σε 32-bit
type για το αποτέλεσμα της malloc ή λείπει το prototype της malloc().
Ειδικά στη δεύτερη περίπτωση ο C compiler εισάγει αυτόματα ένα 'stub'
prototype για τη malloc() του τύπου:
int malloc(...);
Οπότε όταν ένα C source file καλέσει τη malloc() ο compiler θεωρεί ότι
το return value της «χωράει» σε 'int', το οποίο σε 64-bit περιβάλλον
τυχαίνει να είναι 32-bit.
Μια λύση για να έχεις early warning σχετικά με τέτοια bugs είναι να
μεταγλωττίζεις πάντα τον κώδικα με -Wmissing-prototypes και να προσέχεις
ΠΟΛΥ όταν ο μεταγλωττιστής λέει κάτι σαν αυτό:
: keramida at bokos:/home/keramida$ cat -n foo.c
: 1 #include <stdio.h>
: 2
: 3 int
: 4 main(void)
: 5 {
: 6 char *p = malloc(100);
: 7
: 8 p[0] = '\0';
: 9 (void)printf("%s\n", p);
: 10 return 0;
: 11 }
:
: keramida at bokos:/home/keramida$ cc -Wmissing-prototypes foo.c
: foo.c: In function 'main':
: foo.c:6: warning: incompatible implicit declaration of built-in function 'malloc'
Όλα τα 'implicit function declaration' warnings σημαίνουν ότι ο compiler
δεν έχει δει ως εκείνη τη στιγμή 'valid' prototype για τη συγκεκριμένη
function και αυτόματα εισάγει ένα stub declaration της μορφής:
int function(...);
Αυτό μπορεί να είναι από «αθώο» έως και επικίνδυνο, αφού - όπως μόλις
ανακάλυψες - σε αρχιτεκτονικές 64-bit είναι συχνά πολύ σοβαρό bug το να
μην έχεις ορατό prototype για συναρτήσεις οι οποίες επιστρέφουν τιμές
από pointers.
<pedant-rant>
Θεωρητικά οποιαδήποτε συνάρτηση επιστρέφει pointer-value μπορεί να
εμφανίσει το 'clipping των άνω 32-bit' που είδες. Το ακόμα πιο
εντυπωσιακό είναι ότι συνήθως το πρόγραμμα είναι «αρκετά τυχερό» και
τυχαίνει ο runtime loader να το φορτώσει σε διεύθυνση που είναι κάτω από
το όριο των 32-bit διευθύνσεων, π.χ. η main() του είναι σε διεύθυνση
όπως η 0x0000000008048470, τα δεδομένα του είναι επίσης σε χαμηλή
διεύθυνση, σαν την 0x0000000028049000 και _κανείς_ δεν καταλαβαίνει ότι
οι pointers γίνονται 'clip' επειδή ΕΤΥΧΕ να μην πειράζει!
Μέχρι τη μέρα που το ίδιο πρόγραμμα το ενσωματώνεις ως dlopen-able
module σε κάποιο server process, και ο runtime linker αποφασίζει να το
φορτώσει σε high-address. ***CABOOM: OUT OF CHEESE ERROR***
</pedant-rant>
More information about the Linux-greek-users
mailing list