Undefined references to 'memcpy' when compiling Linux Kernel

From: Byron Stanoszek (gandalf@winds.org)
Date: Fri Jun 16 2000 - 08:49:10 EST

Using the latest CVS snapshot for gcc 2.96, I find that 5 functions in the
Linux Kernel (2.4.0) contain 'memcpy' statements that are not correctly
converted into assembly using the compiler's builtin function list.

Instead, the code resulting for these functions is a 'call memcpy', a
function that doesn't exist in the kernel. A -fbuiltin-functions or -O3 does
not seem to solve the problem.

Output of the error:

ld -m elf_i386 -T /usr/src/linux/arch/i386/vmlinux.lds -e stext
arch/i386/kernel/head.o arch/i386/kernel/init_task.o init/main.o
init/version.o \
        --start-group \
        arch/i386/kernel/kernel.o arch/i386/mm/mm.o kernel/kernel.o mm/mm.o
fs/fs.o ipc/ipc.o \
        drivers/block/block.a drivers/char/char.o drivers/misc/misc.o
drivers/net/net.o drivers/parport/parport.a drivers/ide/idedriver.o
drivers/cdrom/cdrom.a drivers/pci/pci.a drivers/video/video.o \
        net/network.o \
        /usr/src/linux/arch/i386/lib/lib.a /usr/src/linux/lib/lib.a
/usr/src/linux/arch/i386/lib/lib.a \
        --end-group \
        -o vmlinux
fs/fs.o: In function `nfs_fhget':
fs/fs.o(.text+0x32d4a): undefined reference to `memcpy'
fs/fs.o: In function `nlmclnt_proc':
fs/fs.o(.text+0x3ae08): undefined reference to `memcpy'
fs/fs.o: In function `nlmclnt_reclaim':
fs/fs.o(.text+0x3b4af): undefined reference to `memcpy'
fs/fs.o: In function `nlmclnt_cancel':
fs/fs.o(.text+0x3b71d): undefined reference to `memcpy'
fs/fs.o: In function `nlm_lookup_file':
fs/fs.o(.text+0x3e92d): undefined reference to `memcpy'
make: *** [vmlinux] Error 1

...in /usr/src/linux/fs/nfs:

gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2
-fomit-frame-pointer -fno-strict-aliasing -pipe -mpreferred-stack-boundary=2
-march=i586 -c -o inode.o inode.c

...containing this function:

struct inode *
nfs_fhget(struct dentry *dentry, struct nfs_fh *fhandle,
                                 struct nfs_fattr *fattr)
        struct super_block *sb = dentry->d_sb;

        dprintk("NFS: nfs_fhget(%s/%s fileid=%Ld)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name,
                (long long)fattr->fileid);

        /* Install the file handle in the dentry */
        *((struct nfs_fh *) dentry->d_fsdata) = *fhandle;

         * Check for NetApp snapshot dentries, and get an
         * unhashed inode to avoid aliasing problems.
        if ((dentry->d_parent->d_inode->u.nfs_i.flags & NFS_IS_SNAPSHOT) ||
            (dentry->d_name.len == 9 &&
             memcmp(dentry->d_name.name, ".snapshot", 9) == 0)) {
                struct inode *inode = get_empty_inode();
                if (!inode)
                        goto out;
                inode->i_sb = sb;
                inode->i_dev = sb->s_dev;
                inode->i_flags = 0;
                inode->i_ino = nfs_fattr_to_ino_t(fattr);
                nfs_fill_inode(inode, fattr);
                inode->u.nfs_i.flags |= NFS_IS_SNAPSHOT;
                dprintk("NFS: nfs_fhget(snapshot ino=%ld)\n", inode->i_ino);
                return inode;
        return __nfs_fhget(sb, fattr);

While there is no reference to 'memcpy' in the above code, it is possible that
the compiler is inserting a 'memcpy' statement as a substitution for an
optimization of some sort.

...The output of the nfs_fhget function in inode.s:

.LC32: .string "NFS: nfs_fhget(%s/%s fileid=%Ld)\n" .LC33: .string ".snapshot" .align 32 .LC34: .string "NFS: nfs_fhget(snapshot ino=%ld)\n" .text .align 16 .globl nfs_fhget .type nfs_fhget,@function nfs_fhget: pushl %ebp pushl %edi pushl %esi pushl %ebx pushl %ebp movl 24(%esp), %ebx movl 32(%esp), %eax movl %eax, (%esp) movl 28(%esp), %esi movl 84(%ebx), %ebp testb $1, nfs_debug je .L2072 movl %eax, %ecx movl 80(%ecx), %edi pushl %edi movl 76(%ecx), %edx pushl %edx movl 64(%ebx), %eax pushl %eax movl 12(%ebx), %eax movl 64(%eax), %edi pushl %edi pushl $.LC32 call printk addl $20, %esp .L2072: pushl $66 pushl %esi movl 92(%ebx), %esi pushl %esi call memcpy <------------------------------- movl 12(%ebx), %eax addl $12, %esp movl 8(%eax), %eax testb $16, 280(%eax) jne .L2077 cmpl $9, 68(%ebx) jne .L2076 cld movl 64(%ebx), %esi movl $.LC33, %edi movl $9, %ecx repz cmpsb seta %dl setb %al cmpb %al, %dl jne .L2076 .L2077: call get_empty_inode movl %eax, %ebx testl %ebx, %ebx je .L2079 movl %ebp, 164(%ebx) movl 8(%ebp), %eax movw %ax, 40(%ebx) movl $0, 244(%ebx) movl (%esp), %ecx movl 76(%ecx), %eax movl 80(%ecx), %edx movl %eax, %ecx movl %edx, %eax xorl %eax, %ecx movl %ecx, 32(%ebx) movl 12(%ebp), %eax movl %eax, 80(%ebx) movw $0, 42(%ebx) movw $0, 56(%ebx) movl $0, 272(%ebx) movl $0, 276(%ebx) movl $0, 264(%ebx) movl $0, 268(%ebx) leal 336(%ebx), %eax movl %eax, 336(%ebx) movl %eax, 340(%ebx) leal 344(%ebx), %eax movl %eax, 344(%ebx) movl %eax, 348(%ebx) leal 352(%ebx), %eax movl %eax, 352(%ebx) movl %eax, 356(%ebx) leal 360(%ebx), %eax movl %eax, 360(%ebx) movl %eax, 364(%ebx) movl $0, 368(%ebx) movl $0, 372(%ebx) movl $0, 376(%ebx) movl $0, 380(%ebx) movl jiffies, %eax movl 228(%ebp), %ecx subl %ecx, %eax decl %eax movl %eax, 284(%ebx) xorl %eax, %eax andl $61440, %eax cmpw $16384, %ax jne .L2089 movl %ebp, %eax movl 232(%eax), %eax jmp .L2090 .p2align 4,,7 .L2089: movl 164(%ebx), %eax movl 224(%eax), %eax .L2090: movl %eax, 320(%ebx) movl jiffies, %eax movl %eax, 324(%ebx) movl (%esp), %edx pushl %edx pushl %ebx call nfs_fill_inode orw $16, 280(%ebx) popl %ebp popl %eax testb $1, nfs_debug je .L2079 movl 32(%ebx), %edi pushl %edi pushl $.LC34 call printk popl %ecx popl %esi .L2079: popl %edx movl %ebx, %eax popl %ebx popl %esi popl %edi popl %ebp ret .p2align 4,,7 .L2076: movl (%esp), %eax movl %ebp, 24(%esp) movl %eax, 28(%esp) popl %eax popl %ebx popl %esi popl %edi popl %ebp jmp __nfs_fhget

--- Another function, for comparison, has this same problem with memcpy:

...in /usr/src/linux/fs/nfs/clntproc.c:

/* * This is the main entry point for the NLM client. */ int nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) { struct nfs_server *nfssrv = NFS_SERVER(inode); struct nlm_host *host; struct nlm_rqst reqst, *call = &reqst; sigset_t oldset; unsigned long flags; int status, proto, vers;

vers = (NFS_PROTO(inode)->version == 3) ? 4 : 1; if (NFS_PROTO(inode)->version > 3) { printk(KERN_NOTICE "NFSv4 file locking not implemented!\n"); return -ENOLCK; }

/* Retrieve transport protocol from NFS client */ proto = NFS_CLIENT(inode)->cl_xprt->prot;

if (!(host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers))) return -ENOLCK;

/* Create RPC client handle if not there, and copy soft * and intr flags from NFS client. */ if (host->h_rpcclnt == NULL) { struct rpc_clnt *clnt;

/* Bind an rpc client to this host handle (does not * perform a portmapper lookup) */ if (!(clnt = nlm_bind_host(host))) { status = -ENOLCK; goto done; } clnt->cl_softrtry = nfssrv->client->cl_softrtry; clnt->cl_intr = nfssrv->client->cl_intr; clnt->cl_chatty = nfssrv->client->cl_chatty; }

/* Keep the old signal mask */ spin_lock_irqsave(&current->sigmask_lock, flags); oldset = current->blocked;

/* If we're cleaning up locks because the process is exiting, * perform the RPC call asynchronously. */ if ((cmd == F_SETLK || cmd == F_SETLKW) && fl->fl_type == F_UNLCK && (current->flags & PF_EXITING)) { sigfillset(&current->blocked); /* Mask all signals */ recalc_sigpending(current); spin_unlock_irqrestore(&current->sigmask_lock, flags);

call = nlmclnt_alloc_call(); if (!call) { status = -ENOMEM; goto out_restore; } call->a_flags = RPC_TASK_ASYNC; } else { spin_unlock_irqrestore(&current->sigmask_lock, flags); call->a_flags = 0; } call->a_host = host;

/* Set up the argument struct */ nlmclnt_setlockargs(call, fl);

if (cmd == F_GETLK) { status = nlmclnt_test(call, fl); } else if ((cmd == F_SETLK || cmd == F_SETLKW) && fl->fl_type == F_UNLCK) { status = nlmclnt_unlock(call, fl); } else if (cmd == F_SETLK || cmd == F_SETLKW) { call->a_args.block = (cmd == F_SETLKW)? 1 : 0; status = nlmclnt_lock(call, fl); } else { status = -EINVAL; }

if (status < 0 && (call->a_flags & RPC_TASK_ASYNC)) kfree(call);

out_restore: spin_lock_irqsave(&current->sigmask_lock, flags); current->blocked = oldset; recalc_sigpending(current); spin_unlock_irqrestore(&current->sigmask_lock, flags);

done: dprintk("lockd: clnt proc returns %d\n", status); nlm_release_host(host); return status; }

...And its assembled output:

.LC22: .string "<5>NFSv4 file locking not implemented!\n" .LC23: .string "lockd: clnt proc returns %d\n" .text .align 16 .globl nlmclnt_proc .type nlmclnt_proc,@function nlmclnt_proc: pushl %ebp pushl %edi pushl %esi pushl %ebx subl $508, %esp movl 528(%esp), %eax leal 12(%esp), %ebp movl 164(%eax), %ebx movl 192(%ebx), %eax movl (%eax), %edx xorl %eax, %eax cmpl $3, %edx sete %al leal 1(%eax,%eax,2), %ecx jle .L1773 pushl $.LC22 call printk popl %edi movl $-37, %eax jmp .L1770 .p2align 4,,7 .L1773: movl 188(%ebx), %eax movl 4(%eax), %eax pushl %ecx movl 48(%eax), %esi pushl %esi movl 188(%ebx), %eax movl 4(%eax), %eax addl $32, %eax pushl %eax call nlmclnt_lookup_host movl %eax, 20(%esp) addl $12, %esp testl %eax, %eax jne .L1774 movl $-37, %eax jmp .L1770 .p2align 4,,7 .L1774: movl 8(%esp), %eax movl 24(%eax), %ecx testl %ecx, %ecx jne .L1775 pushl %eax call nlm_bind_host movl %eax, %ecx popl %edx movl $-37, %esi testl %ecx, %ecx je .L1777 movl 188(%ebx), %eax movb 32(%eax), %dl movb 32(%ecx), %al andl $1, %edx andl $254, %eax orl %edx, %eax movb %al, 32(%ecx) andl $-3, %eax movl 188(%ebx), %edx movb 32(%edx), %dl andl $2, %edx orl %edx, %eax movb %al, 32(%ecx) andl $-5, %eax movl 188(%ebx), %edx movb 32(%edx), %dl andl $4, %edx orl %edx, %eax movb %al, 32(%ecx) .L1775: #APP pushfl ; popl %ebx ; cli #NO_APP movl $-8192, %edx #APP andl %esp,%edx; #NO_APP movl 532(%esp), %eax movl 956(%edx), %esi movl 960(%edx), %edi movl %esi, (%esp) subl $6, %eax movl %edi, 4(%esp) cmpl $1, %eax ja .L1784 movl 536(%esp), %edi cmpb $2, 53(%edi) jne .L1784 testb $4, 4(%edx) je .L1784 movl $-1, 960(%edx) movl $-1, 956(%edx) movl $0, 8(%edx) #APP pushl %ebx ; popfl #NO_APP call nlmclnt_alloc_call movl $-12, %esi movl %eax, %ebp testl %ebp, %ebp je .L1802 movl $2, (%ebp) jmp .L1803 .p2align 4,,7 .L1784: #APP pushl %ebx ; popfl #NO_APP movl $0, (%ebp) .L1803: movl 8(%esp), %eax leal 8(%ebp), %edx movl %eax, 4(%ebp) xorl %eax, %eax leal 20(%ebp), %ebx movl $53, %ecx movl %edx, %edi #APP rep ; stosl #NO_APP movl nlm_cookie, %eax movl %eax, 8(%ebp) movl $0, 12(%ebp) movl nlm_cookie, %eax incl %eax movl $4, 8(%edx) movl %eax, nlm_cookie movl nsm_local_state, %eax movl %eax, 196(%edx) movl 536(%esp), %edx movl 48(%edx), %eax leal 24(%ebp), %edx movl 8(%eax), %eax pushl $66 movl 92(%eax), %edi pushl %edi leal 100(%ebp), %edi pushl %edx call memcpy <----------------------------- leal 412(%ebp), %edx movl $-8192, %eax movl $system_utsname+65, 20(%ebp) #APP andl %esp,%eax; #NO_APP movl %edx, 76(%ebx) pushl $system_utsname+65 movl 104(%eax), %esi pushl %esi pushl $.LC21 pushl %edx call sprintf cld movl %eax, 72(%ebx) movl $24, %ecx movl 564(%esp), %esi addl $28, %esp rep movsl cmpl $5, 532(%esp) jne .L1835 movl 536(%esp), %ebx pushl %ebx pushl %ebp call nlmclnt_test jmp .L1865 .p2align 4,,7 .L1835: movl 532(%esp), %eax subl $6, %eax cmpl $1, %eax ja .L1837 movl 536(%esp), %esi cmpb $2, 53(%esi) jne .L1837 pushl %esi pushl %ebp call nlmclnt_unlock popl %edi movl %eax, %esi popl %eax jmp .L1836 .p2align 4,,7 .L1837: movl 532(%esp), %eax subl $6, %eax cmpl $1, %eax ja .L1839 xorl %eax, %eax cmpl $7, 532(%esp) sete %al movl %eax, 196(%ebp) movl 536(%esp), %ebx pushl %ebx pushl %ebp call nlmclnt_lock .L1865: popl %edx movl %eax, %esi popl %ecx jmp .L1836 .p2align 4,,7 .L1839: movl $-22, %esi .L1836: testl %esi, %esi jns .L1802 testl $2, (%ebp) je .L1802 pushl %ebp call kfree popl %eax .L1802: #APP pushfl ; popl %ebx ; cli #NO_APP movl $-8192, %ecx #APP andl %esp,%ecx; #NO_APP movl 4(%esp), %edx movl (%esp), %eax movl %edx, 960(%ecx) movl %eax, 956(%ecx) movl 960(%ecx), %edx movl 956(%ecx), %eax xorl $-1, %edx movl 952(%ecx), %ebp xorl $-1, %eax movl 948(%ecx), %edi andl %ebp, %edx andl %edi, %eax orl %eax, %edx xorl %eax, %eax testl %edx, %edx setne %al movl %eax, 8(%ecx) #APP pushl %ebx ; popfl #NO_APP .L1777: testb $2, nlm_debug je .L1861 pushl %esi pushl $.LC23 call printk popl %edx popl %ecx .L1861: movl 8(%esp), %eax pushl %eax call nlm_release_host popl %ebp movl %esi, %eax .L1770: addl $508, %esp popl %ebx popl %esi popl %edi popl %ebp ret

Any ideas?

-- Byron Stanoszek Ph: (330) 644-3059 Systems Programmer Fax: (330) 644-8110 Commercial Timesharing Inc. Email: bstanoszek@comtime.com

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/

This archive was generated by hypermail 2b29 : Fri Jun 23 2000 - 21:00:13 EST