LINTDUMP(1ONBLD) | illumos Build Tools | LINTDUMP(1ONBLD) |
A lint object is a binary file (typically suffixed with ".ln") constructed from a C source file via the "-c" option to lint(1). Multiple lint objects may be combined into a lint library object (typically prefixed with "llib-l" and suffixed with ".ln") using the "-o" option to lint. (As a convenience, lint "-o" allows a lint library object to be built directly from C source files). The lintdump utility is capable of dumping both traditional lint objects and lint library objects.
The format of a lint object is unstable and subject to change at any time, but its current structure is summarized here in order to aid in understanding the current output of lintdump. A lint object consists of one or more lint modules (one per C source file). Each lint module consists of a header and four sections, called PASS1, PASS2, PASS3, and STRINGS. Generally speaking, PASS1 contains definitions, PASS2 contains declarations, and PASS3 contains information on whether or how functions or variables are used. The STRINGS section holds the strings for printf(3C)/scanf(3C) checking.
Each PASS section consists of a sequence of binary records of assorted types. The sequence of records is further partitioned by FILE records, which indicate the source or header file that is responsible for the records that follow. The remaining record types provide lint with information about the functions, variables, and structures defined or used by the object.
Next, unless the -p option is used, the contents of the PASS1, PASS2, and PASS3 sections are dumped, in order. Before each section is dumped, lintdump outputs a single line beginning with "SECTION:" that provides the name and size of the section. For each section, lintdump outputs each record in order. The display format of each record depends on its type:
FILE RECORDS
FUNCTION AND VARIABLE RECORDS
STRUCTURE AND UNION RECORDS
To illustrate each of the common record formats, suppose the following lint library is built:
$ cat > liba.c
/* LINTLIBRARY */
/* PROTOLIB1 */
int af(int);
struct as {
char as_name[32];
int as_flag;
} as;
$ lint -oa liba.c
Then lintdump will produce the following output:
LINTOBJ: llib-la.ln
LINTMOD: 6484: 268+24+130+9 = 431 bytes
SECTION: PASS1: 268 bytes
FILE: /home/meem/hacks/liba.c
FILE: liba.c
extern int af(int);
struct as as;
struct as <tag 98> {
char as_name[];
int as_flag;
};
SECTION: PASS2: 24 bytes
SECTION: PASS3: 130 bytes
FILE: /home/meem/hacks/liba.c
FILE: liba.c
int af(void) <returns value>;
<PRINTFLIKEn>
<SCANFLIKEn>
<definition>
<use: side-effects context>
<use: return value context>
<use: unspecified context>
<returns value>
$ lint msghdr.c -lsocket
function argument ( number ) used inconsistently
recvmsg (arg 2) llib-lsocket:socket.h(437) struct msghdr * ::
msghdr.c(12) struct msghdr *
By using lintdump, we can pinpoint the problem by examining both definitions for struct msghdr:
$ lintdump /lib/llib-lsocket.ln
[ ... ]
FILE: llib-lsocket:socket.h
struct msghdr <tag 4532> {
void *msg_name;
unsigned int msg_namelen;
struct iovec *msg_iov;
int msg_iovlen;
char *msg_accrights;
int msg_accrightslen;
};
$ lint -omsghdr msghdr.c -lsocket
$ lintdump llib-lmsghdr.ln
[ ... ]
FILE: socket.h
struct msghdr <tag 1315> {
void *msg_name;
unsigned int msg_namelen;
struct iovec *msg_iov;
int msg_iovlen;
void *msg_control;
unsigned int msg_controllen;
int msg_flags;
};
Looking at <sys/socket.h>, the problem becomes apparent: the structure changes depending on compile-time options, which clearly differ between the application and the library:
struct msghdr {
void *msg_name;
socklen_t msg_namelen;
struct iovec *msg_iov;
int msg_iovlen;
#if defined(_XPG4_2) || defined(_KERNEL)
void *msg_control;
socklen_t msg_controllen;
int msg_flags;
#else
caddr_t msg_accrights;
int msg_accrightslen;
#endif /* defined(_XPG4_2) || defined(_KERNEL) */
};
Another use of lintdump is to compare two versions of a lint object to see whether anything of significance has changed. For instance, lintdump can be used to understand why a lint library is different between a project gate and a patch gate, and thus to determine whether the library will need to be redelivered in the patch including the project:
$ PATCHROOT=/ws/on10-patch/proto/root_i386
$ diff llib-lkstat.ln $PATCHROOT/lib/llib-lkstat.ln
Binary files llib-lkstat.ln and
/ws/on10-patch/proto/root_i386/lib/llib-lkstat.ln differ
$ lintdump -ir llib-lkstat.ln > /tmp/proj-kstat.out
$ lintdump -ir $PATCHROOT/lib/llib-lkstat.ln > /tmp/patch-kstat.out
$ diff /tmp/patch-kstat.out /tmp/proj-kstat.out
1,2c1,2
< LINTMOD: 3675: 4995+26812+1045+9 = 32861 bytes
< SECTION: PASS1: 4995 bytes
---
> LINTMOD: 39982: 5144+27302+1057+9 = 33512 bytes
> SECTION: PASS1: 5144 bytes
19c19
< unsigned char _file;
---
> unsigned char _magic;
22a23,24
> unsigned int __extendedfd;
> unsigned int __xf_nocheck;
[ ... ]
Note that -r option removes spurious differences that would otherwise arise from different absolute paths to the same source file, and the -i option removes spurious differences due to ID generation inside lint.
The lint object file format does not have a way to represent bitfields. As such, bitfield size information cannot be displayed by lintdump.
March 28, 2008 |