Libc strcpy usage on kernels
Table of Contents
1 Introduction
A simple search for a common libc function, strpcy, on various kernels. What it proves? Nothing… it's just a reflect of the organization of the code.
1.1 Linux
In the moment, 3 somewhat redundant functions.
- http://lxr.linux.no/#linux+v3.5/arch/x86/lib/string_32.c#L17
char *strcpy(char *dest, const char *src) { int d0, d1, d2; asm volatile("1:\tlodsb\n\t" "stosb\n\t" "testb %%al,%%al\n\t" "jne 1b" : "=&S" (d0), "=&D" (d1), "=&a" (d2) : "0" (src), "1" (dest) : "memory"); return dest; }
- http://lxr.linux.no/#linux+v3.5/lib/string.c#L97
char *strcpy(char *dest, const char *src) { char *tmp = dest; while ((*dest++ = *src++) != '\0') /* nothing */; return tmp; }
- http://lxr.linux.no/#linux+v3.5/arch/m68k/include/asm/string.h#L16
static inline char *__kernel_strcpy(char *dest, const char *src) { char *xdest = dest; asm volatile ("\n" "1: move.b (%1)+,(%0)+\n" " jne 1b" : "+a" (dest), "+a" (src) : : "memory"); return xdest; }
1.2 Darwin/XNU (Mac OS)
At the moment, only 1 declaration.
- http://lxr.linux.no/#darwin-xnu+792.6.76/osfmk/device/subrs.c#L220
char * strcpy( register char *to, register const char *from) { register char *ret = to; while ((*to++ = *from++) != '\0') continue; return ret; }
1.3 DragonflyBSD
3 functions, but 2 is for GDB support (according to the files…)
- http://fxr.watson.org/fxr/source/libkern/strcpy.c?v=DFBSD#L40
char * strcpy(char * __restrict to, const char * __restrict from) { char *save = to; for (; (*to = *from) != 0; ++from, ++to); return(save); }
- GDB functions:
1.4 OpenBSD
No version of strcpy is found… But we have strncpy, bonus security points :)… But, 3 strncpy declarations… :(
- http://fxr.watson.org/fxr/source/lib/libkern/strncpy.c?v=OPENBSD#L50
The interesting thing, is,
#if !defined(_KERNEL) && !defined(_STANDALONE)
, it uses<string.h>
. Interesting…char * strncpy(char *dst, const char *src, size_t n) { if (n != 0) { char *d = dst; const char *s = src; do { if ((*d++ = *s++) == 0) { /* NUL pad the remaining n-1 bytes */ while (--n != 0) *d++ = 0; break; } } while (--n != 0); } return (dst); }
- http://fxr.watson.org/fxr/source/lib/libsa/strncpy.c?v=OPENBSD#L34
char * strncpy(char *s1, const char *s2, size_t n) { char *p = s1; while (n-- && (*s1++ = *s2++) != '\0') ; return p; }
- http://fxr.watson.org/fxr/source/arch/vax/include/macros.h?v=OPENBSD#L164
static __inline__ char * strncpy(char *cp, const char *c2, size_t len) { __asm__ __volatile("movl %2,r2;locc $0,r2,(%1);beql 1f;subl3 r0,%2,r2; clrb (%0)[r2];1:;movc3 r2,(%1),(%0)" : : "r" (cp), "r" (c2), "g"(len) : "r0","r1","r2","r3","r4","r5","memory","cc"); return cp; }
1.5 NetBSD
It uses GCC __builtin_strcpy
, unless on VAX or if defined
_STANDALONE
, in which case it uses a callback table, and I had not
found the function declaration yet.
- http://fxr.watson.org/fxr/source/lib/libkern/libkern.h?v=NETBSD#L273
/* Prototypes for which GCC built-ins exist. */ void *memcpy(void *, const void *, size_t); int memcmp(const void *, const void *, size_t); void *memset(void *, int, size_t); #if __GNUC_PREREQ__(2, 95) && (__GNUC_PREREQ__(4, 0) || !defined(__vax__)) && \ !defined(_STANDALONE) #define memcpy(d, s, l) __builtin_memcpy(d, s, l) #define memcmp(a, b, l) __builtin_memcmp(a, b, l) #endif #if __GNUC_PREREQ__(2, 95) && !defined(__vax__) && !defined(_STANDALONE) #define memset(d, v, l) __builtin_memset(d, v, l) #endif char *strcpy(char *, const char *); int strcmp(const char *, const char *); size_t strlen(const char *); char *strsep(char **, const char *); #if __GNUC_PREREQ__(2, 95) && !defined(_STANDALONE) #define strcpy(d, s) __builtin_strcpy(d, s) #define strcmp(a, b) __builtin_strcmp(a, b) #define strlen(a) __builtin_strlen(a) #endif
- VAX version:
http://fxr.watson.org/fxr/source/arch/vax/include/macros.h?v=NETBSD#L197
static __inline char * __attribute__((__unused__)) strcpy(char *cp, const char *c2) { __asm volatile("locc $0,$65535,(%1);" "subl3 %%r0,$65535,%%r2;" "movc3 %%r2,(%1),(%0);" "movb $0,(%%r3)" : : "r" (cp), "r" (c2) : "r0","r1","r2","r3","r4","r5","memory","cc"); return cp; }
1.6 Minix
No declaration, uses compilling host libc
1.7 OpenSolaris
Defined as bcopy
, which is defined as memmove
, wich I found no
definition… I supose it's using <string.h>
memmove
- http://fxr.watson.org/fxr/source/common/gssapi/mechs/krb5/include/krb5.h?v=OPENSOLARIS#L100
#define strcpy(dst,src,n) bcopy((src),(dst),(n))
1.8 March
1 definition
- http://fxr.watson.org/fxr/source/kern/strings.c?v=MK84#L128
char * strcpy( register char *to, register const char *from) { register char *ret = to; while ((*to++ = *from++) != '\0') continue; return ret; }
1.9 Plan9
1 external definition, assuming GCC builtin…
- http://fxr.watson.org/fxr/source/port/lib.h?v=PLAN9#L24
extern char* strcpy(char*, char*);
1.10 FreeBSD
3 definitions, with one somewhat invalid, and some use of builtin functions
- http://fxr.watson.org/fxr/source/boot/arm/at91/libat91/strcpy.c#L32
char * strcpy(char *to, const char *from) { while (*from) *to++ = *from++; *to++ = '\0'; return (to); }
- http://fxr.watson.org/fxr/source/boot/common/util.c#L77
I think it must return the destination pointer…
void strcpy(char *dst, const char *src) { while (*src != '\0') *dst++ = *src++; *dst = '\0'; }
- http://fxr.watson.org/fxr/source/libkern/strcpy.c#L36
char * strcpy(char * __restrict to, const char * __restrict from) { char *save = to; for (; (*to = *from) != 0; ++from, ++to); return(save); }
- http://fxr.watson.org/fxr/source/dev/hpt27xx/osm.h#L202
#define strcpy(dst, src) __builtin_strcpy((dst), (src))
- http://fxr.watson.org/fxr/source/dev/hptrr/osm.h#L168
#define strcpy(dst, src) __builtin_strcpy((dst), (src))