diff options
-rw-r--r-- | libc/Android.mk | 4 | ||||
-rw-r--r-- | libc/bionic/eabi.c | 5 | ||||
-rw-r--r-- | libc/bionic/pthread.c | 15 | ||||
-rw-r--r-- | libc/bionic/stubs.c | 172 | ||||
-rw-r--r-- | libc/bionic/time64.c | 793 | ||||
-rw-r--r-- | libc/bionic/time64_config.h | 75 | ||||
-rw-r--r-- | libc/docs/OVERVIEW.TXT | 364 | ||||
-rw-r--r-- | libc/include/pthread.h | 6 | ||||
-rw-r--r-- | libc/include/string.h | 5 | ||||
-rw-r--r-- | libc/include/sys/stat.h | 4 | ||||
-rw-r--r-- | libc/include/sys/time.h | 2 | ||||
-rw-r--r-- | libc/include/sys/types.h | 1 | ||||
-rw-r--r-- | libc/include/time64.h | 54 | ||||
-rw-r--r-- | libc/include/unistd.h | 4 | ||||
-rwxr-xr-x | libc/string/strcoll.c | 40 | ||||
-rwxr-xr-x | libc/string/strxfrm.c | 47 | ||||
-rwxr-xr-x | libdl/dltest.c | 266 | ||||
-rw-r--r-- | linker/arch/arm/begin.S | 28 | ||||
-rw-r--r-- | linker/arch/x86/begin.S | 29 | ||||
-rw-r--r-- | linker/debugger.c | 31 | ||||
-rw-r--r-- | linker/linker.c | 28 | ||||
-rw-r--r-- | linker/linker.h | 28 | ||||
-rw-r--r-- | linker/linker_debug.h | 28 | ||||
-rw-r--r-- | linker/rt.c | 28 |
24 files changed, 1877 insertions, 180 deletions
diff --git a/libc/Android.mk b/libc/Android.mk index f950c7e..330802a 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -66,6 +66,7 @@ libc_common_src_files := \ unistd/usleep.c \ unistd/wait.c \ stdio/asprintf.c \ + stdio/clrerr.c \ stdio/fclose.c \ stdio/fdopen.c \ stdio/feof.c \ @@ -179,6 +180,7 @@ libc_common_src_files := \ string/strcat.c \ string/strchr.c \ string/strcmp.c \ + string/strcoll.c \ string/strcpy.c \ string/strcspn.c \ string/strdup.c \ @@ -198,6 +200,7 @@ libc_common_src_files := \ string/strstr.c \ string/strtok.c \ string/strtotimeval.c \ + string/strxfrm.c \ inet/bindresvport.c \ inet/inet_addr.c \ inet/inet_aton.c \ @@ -234,6 +237,7 @@ libc_common_src_files := \ bionic/ssp.c \ bionic/stubs.c \ bionic/system_properties.c \ + bionic/time64.c \ bionic/thread_atexit.c \ bionic/utime.c \ bionic/utmp.c \ diff --git a/libc/bionic/eabi.c b/libc/bionic/eabi.c index c491f05..f212d05 100644 --- a/libc/bionic/eabi.c +++ b/libc/bionic/eabi.c @@ -30,7 +30,10 @@ void* __dso_handle = 0; -int __aeabi_atexit (void *object, void (*destructor) (void *), void *dso_handle) +/* Make this a weak symbol to avoid a multiple definition error when linking + * with libstdc++-v3. */ +int __attribute__((weak)) +__aeabi_atexit (void *object, void (*destructor) (void *), void *dso_handle) { //return __cxa_atexit(destructor, object, dso_handle); return 0; diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c index 6114f40..ec3c459 100644 --- a/libc/bionic/pthread.c +++ b/libc/bionic/pthread.c @@ -488,6 +488,21 @@ int pthread_getattr_np(pthread_t thid, pthread_attr_t * attr) return 0; } +int pthread_attr_setscope(pthread_attr_t *attr, int scope) +{ + if (scope == PTHREAD_SCOPE_SYSTEM) + return 0; + if (scope == PTHREAD_SCOPE_PROCESS) + return ENOTSUP; + + return EINVAL; +} + +int pthread_attr_getscope(pthread_attr_t const *attr) +{ + return PTHREAD_SCOPE_SYSTEM; +} + /* CAVEAT: our implementation of pthread_cleanup_push/pop doesn't support C++ exceptions * and thread cancelation diff --git a/libc/bionic/stubs.c b/libc/bionic/stubs.c index 1f76bba..365f21a 100644 --- a/libc/bionic/stubs.c +++ b/libc/bionic/stubs.c @@ -35,6 +35,7 @@ #include <pthread.h> #include <stdlib.h> #include <errno.h> +#include <ctype.h> /** Thread-specific state for the stubs functions **/ @@ -95,8 +96,9 @@ __stubs_state(void) return s; } -static struct passwd *android_iinfo_to_passwd( - struct passwd *pw, struct android_id_info *iinfo) +static struct passwd* +android_iinfo_to_passwd( struct passwd *pw, + struct android_id_info *iinfo ) { pw->pw_name = (char*)iinfo->name; pw->pw_uid = iinfo->aid; @@ -106,8 +108,9 @@ static struct passwd *android_iinfo_to_passwd( return pw; } -static struct group *android_iinfo_to_group( - struct group *gr, struct android_id_info *iinfo) +static struct group* +android_iinfo_to_group( struct group *gr, + struct android_id_info *iinfo ) { gr->gr_name = (char*) iinfo->name; gr->gr_gid = iinfo->aid; @@ -116,8 +119,8 @@ static struct group *android_iinfo_to_group( return gr; } -static struct passwd *android_id_to_passwd( - struct passwd *pw, unsigned id) +static struct passwd * +android_id_to_passwd( struct passwd *pw, unsigned id) { struct android_id_info *iinfo = android_ids; unsigned n; @@ -126,11 +129,11 @@ static struct passwd *android_id_to_passwd( return android_iinfo_to_passwd(pw, iinfo + n); } } - return 0; + return NULL; } -static struct passwd *android_name_to_passwd( - struct passwd *pw, const char *name) +static struct passwd* +android_name_to_passwd(struct passwd *pw, const char *name) { struct android_id_info *iinfo = android_ids; unsigned n; @@ -139,11 +142,11 @@ static struct passwd *android_name_to_passwd( return android_iinfo_to_passwd(pw, iinfo + n); } } - return 0; + return NULL; } -static struct group *android_id_to_group( - struct group *gr, unsigned id) +static struct group* +android_id_to_group( struct group *gr, unsigned id ) { struct android_id_info *iinfo = android_ids; unsigned n; @@ -152,11 +155,11 @@ static struct group *android_id_to_group( return android_iinfo_to_group(gr, iinfo + n); } } - return 0; + return NULL; } -static struct group *android_name_to_group( - struct group *gr, const char *name) +static struct group* +android_name_to_group( struct group *gr, const char *name ) { struct android_id_info *iinfo = android_ids; unsigned n; @@ -165,21 +168,47 @@ static struct group *android_name_to_group( return android_iinfo_to_group(gr, iinfo + n); } } - return 0; + return NULL; } -struct passwd* getpwuid(uid_t uid) +/* translate a user/group name like app_1234 into the + * corresponding user/group id (AID_APP + 1234) + * returns 0 and sets errno to ENOENT in case of error + */ +static unsigned +app_id_from_name( const char* name ) { - stubs_state_t* state = __stubs_state(); - struct passwd* pw; + unsigned long id; + char* end; - if (state == NULL) - return NULL; + if (memcmp(name, "app_", 4) != 0 || !isdigit(name[4])) + goto FAIL; - pw = &state->passwd; + id = strtoul(name+4, &end, 10); + if (id == 0 || *end != '\0') + goto FAIL; - if ( android_id_to_passwd(pw, uid) != NULL ) - return pw; + id += AID_APP; + + /* check for overflow and that the value can be + * stored in our 32-bit uid_t/gid_t */ + if (id < AID_APP || (unsigned)id != id) + goto FAIL; + + return (unsigned)id; + +FAIL: + errno = ENOENT; + return 0; +} + +/* translate a uid into the corresponding app_<uid> + * passwd structure (sets errno to ENOENT on failure) + */ +static struct passwd* +app_id_to_passwd(uid_t uid, stubs_state_t* state) +{ + struct passwd* pw = &state->passwd; if (uid < AID_APP) { errno = ENOENT; @@ -187,7 +216,7 @@ struct passwd* getpwuid(uid_t uid) } snprintf( state->app_name_buffer, sizeof state->app_name_buffer, - "app_%d", uid - AID_APP ); + "app_%u", uid - AID_APP ); pw->pw_name = state->app_name_buffer; pw->pw_dir = "/data"; @@ -198,18 +227,66 @@ struct passwd* getpwuid(uid_t uid) return pw; } -struct passwd* getpwnam(const char *login) +/* translate a gid into the corresponding app_<gid> + * group structure (sets errno to ENOENT on failure) + */ +static struct group* +app_id_to_group(gid_t gid, stubs_state_t* state) +{ + struct group* gr = &state->group; + + if (gid < AID_APP) { + errno = ENOENT; + return NULL; + } + + snprintf(state->group_name_buffer, sizeof state->group_name_buffer, + "app_%u", gid - AID_APP); + + gr->gr_name = state->group_name_buffer; + gr->gr_gid = gid; + gr->gr_mem[0] = gr->gr_name; + gr->gr_mem[1] = NULL; + + return gr; +} + + +struct passwd* +getpwuid(uid_t uid) +{ + stubs_state_t* state = __stubs_state(); + struct passwd* pw; + + if (state == NULL) + return NULL; + + pw = &state->passwd; + + if ( android_id_to_passwd(pw, uid) != NULL ) + return pw; + + return app_id_to_passwd(uid, state); +} + +struct passwd* +getpwnam(const char *login) { stubs_state_t* state = __stubs_state(); if (state == NULL) return NULL; - return android_name_to_passwd(&state->passwd, login); + if (android_name_to_passwd(&state->passwd, login) != NULL) + return &state->passwd; + + return app_id_to_passwd( app_id_from_name(login), state ); } -int getgrouplist (const char *user, gid_t group, - gid_t *groups, int *ngroups) { +int +getgrouplist (const char *user, gid_t group, + gid_t *groups, int *ngroups) +{ if (*ngroups < 1) { *ngroups = 1; return -1; @@ -218,18 +295,20 @@ int getgrouplist (const char *user, gid_t group, return (*ngroups = 1); } -char* getlogin(void) +char* +getlogin(void) { struct passwd *pw = getpwuid(getuid()); if(pw) { return pw->pw_name; } else { - return 0; + return NULL; } } -struct group* getgrgid(gid_t gid) +struct group* +getgrgid(gid_t gid) { stubs_state_t* state = __stubs_state(); struct group* gr; @@ -241,34 +320,25 @@ struct group* getgrgid(gid_t gid) if (gr != NULL) return gr; - if (gid < AID_APP) { - errno = ENOENT; - return NULL; - } - - snprintf(state->group_name_buffer, sizeof state->group_name_buffer, - "app_%d", gid - AID_APP); - - gr = &state->group; - - gr->gr_name = state->group_name_buffer; - gr->gr_gid = gid; - gr->gr_mem[0] = gr->gr_name; - gr->gr_mem[1] = NULL; - - return gr; + return app_id_to_group(gid, state); } -struct group* getgrnam(const char *name) +struct group* +getgrnam(const char *name) { stubs_state_t* state = __stubs_state(); + unsigned id; if (state == NULL) return NULL; - return android_name_to_group(&state->group, name); + if (android_name_to_group(&state->group, name) != 0) + return &state->group; + + return app_id_to_group( app_id_from_name(name), state ); } + struct netent* getnetbyname(const char *name) { fprintf(stderr, "FIX ME! implement getgrnam() %s:%d\n", __FILE__, __LINE__); @@ -308,5 +378,3 @@ struct protoent *getprotobynumber(int proto) fprintf(stderr, "FIX ME! implement %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); return NULL; } - - diff --git a/libc/bionic/time64.c b/libc/bionic/time64.c new file mode 100644 index 0000000..1e1f881 --- /dev/null +++ b/libc/bionic/time64.c @@ -0,0 +1,793 @@ +/* + +Copyright (c) 2007-2008 Michael G Schwern + +This software originally derived from Paul Sheer's pivotal_gmtime_r.c. + +The MIT License: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +/* See http://code.google.com/p/y2038 for this code's origin */ + +/* + +Programmers who have available to them 64-bit time values as a 'long +long' type can use localtime64_r() and gmtime64_r() which correctly +converts the time even on 32-bit systems. Whether you have 64-bit time +values will depend on the operating system. + +localtime64_r() is a 64-bit equivalent of localtime_r(). + +gmtime64_r() is a 64-bit equivalent of gmtime_r(). + +*/ + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <errno.h> +#include "time64.h" + +/* BIONIC_BEGIN */ +/* the following are here to avoid exposing time64_config.h and + * other types in our public time64.h header + */ +#include "time64_config.h" + +/* Not everyone has gm/localtime_r(), provide a replacement */ +#ifdef HAS_LOCALTIME_R +# define LOCALTIME_R(clock, result) localtime_r(clock, result) +#else +# define LOCALTIME_R(clock, result) fake_localtime_r(clock, result) +#endif +#ifdef HAS_GMTIME_R +# define GMTIME_R(clock, result) gmtime_r(clock, result) +#else +# define GMTIME_R(clock, result) fake_gmtime_r(clock, result) +#endif + +typedef int64_t Int64; +typedef time64_t Time64_T; +typedef int64_t Year; +#define TM tm +/* BIONIC_END */ + +/* Spec says except for stftime() and the _r() functions, these + all return static memory. Stabbings! */ +static struct TM Static_Return_Date; +static char Static_Return_String[35]; + +static const int days_in_month[2][12] = { + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, +}; + +static const int julian_days_by_month[2][12] = { + {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, + {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}, +}; + +static char const wday_name[7][3] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +static char const mon_name[12][3] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +static const int length_of_year[2] = { 365, 366 }; + +/* Some numbers relating to the gregorian cycle */ +static const Year years_in_gregorian_cycle = 400; +#define days_in_gregorian_cycle ((365 * 400) + 100 - 4 + 1) +static const Time64_T seconds_in_gregorian_cycle = days_in_gregorian_cycle * 60LL * 60LL * 24LL; + +/* Year range we can trust the time funcitons with */ +#define MAX_SAFE_YEAR 2037 +#define MIN_SAFE_YEAR 1971 + +/* 28 year Julian calendar cycle */ +#define SOLAR_CYCLE_LENGTH 28 + +/* Year cycle from MAX_SAFE_YEAR down. */ +static const int safe_years_high[SOLAR_CYCLE_LENGTH] = { + 2016, 2017, 2018, 2019, + 2020, 2021, 2022, 2023, + 2024, 2025, 2026, 2027, + 2028, 2029, 2030, 2031, + 2032, 2033, 2034, 2035, + 2036, 2037, 2010, 2011, + 2012, 2013, 2014, 2015 +}; + +/* Year cycle from MIN_SAFE_YEAR up */ +static const int safe_years_low[SOLAR_CYCLE_LENGTH] = { + 1996, 1997, 1998, 1971, + 1972, 1973, 1974, 1975, + 1976, 1977, 1978, 1979, + 1980, 1981, 1982, 1983, + 1984, 1985, 1986, 1987, + 1988, 1989, 1990, 1991, + 1992, 1993, 1994, 1995, +}; + +/* This isn't used, but it's handy to look at */ +static const int dow_year_start[SOLAR_CYCLE_LENGTH] = { + 5, 0, 1, 2, /* 0 2016 - 2019 */ + 3, 5, 6, 0, /* 4 */ + 1, 3, 4, 5, /* 8 1996 - 1998, 1971*/ + 6, 1, 2, 3, /* 12 1972 - 1975 */ + 4, 6, 0, 1, /* 16 */ + 2, 4, 5, 6, /* 20 2036, 2037, 2010, 2011 */ + 0, 2, 3, 4 /* 24 2012, 2013, 2014, 2015 */ +}; + +/* Let's assume people are going to be looking for dates in the future. + Let's provide some cheats so you can skip ahead. + This has a 4x speed boost when near 2008. +*/ +/* Number of days since epoch on Jan 1st, 2008 GMT */ +#define CHEAT_DAYS (1199145600 / 24 / 60 / 60) +#define CHEAT_YEARS 108 + +#define IS_LEAP(n) ((!(((n) + 1900) % 400) || (!(((n) + 1900) % 4) && (((n) + 1900) % 100))) != 0) +#define WRAP(a,b,m) ((a) = ((a) < 0 ) ? ((b)--, (a) + (m)) : (a)) + +#ifdef USE_SYSTEM_LOCALTIME +# define SHOULD_USE_SYSTEM_LOCALTIME(a) ( \ + (a) <= SYSTEM_LOCALTIME_MAX && \ + (a) >= SYSTEM_LOCALTIME_MIN \ +) +#else +# define SHOULD_USE_SYSTEM_LOCALTIME(a) (0) +#endif + +#ifdef USE_SYSTEM_GMTIME +# define SHOULD_USE_SYSTEM_GMTIME(a) ( \ + (a) <= SYSTEM_GMTIME_MAX && \ + (a) >= SYSTEM_GMTIME_MIN \ +) +#else +# define SHOULD_USE_SYSTEM_GMTIME(a) (0) +#endif + +/* Multi varadic macros are a C99 thing, alas */ +#ifdef TIME_64_DEBUG +# define TRACE(format) (fprintf(stderr, format)) +# define TRACE1(format, var1) (fprintf(stderr, format, var1)) +# define TRACE2(format, var1, var2) (fprintf(stderr, format, var1, var2)) +# define TRACE3(format, var1, var2, var3) (fprintf(stderr, format, var1, var2, var3)) +#else +# define TRACE(format) ((void)0) +# define TRACE1(format, var1) ((void)0) +# define TRACE2(format, var1, var2) ((void)0) +# define TRACE3(format, var1, var2, var3) ((void)0) +#endif + + +static int is_exception_century(Year year) +{ + int is_exception = ((year % 100 == 0) && !(year % 400 == 0)); + TRACE1("# is_exception_century: %s\n", is_exception ? "yes" : "no"); + + return(is_exception); +} + + +/* timegm() is not in the C or POSIX spec, but it is such a useful + extension I would be remiss in leaving it out. Also I need it + for localtime64() +*/ +Time64_T timegm64(const struct TM *date) { + Time64_T days = 0; + Time64_T seconds = 0; + Year year; + Year orig_year = (Year)date->tm_year; + int cycles = 0; + + if( orig_year > 100 ) { + cycles = (orig_year - 100) / 400; + orig_year -= cycles * 400; + days += (Time64_T)cycles * days_in_gregorian_cycle; + } + else if( orig_year < -300 ) { + cycles = (orig_year - 100) / 400; + orig_year -= cycles * 400; + days += (Time64_T)cycles * days_in_gregorian_cycle; + } + TRACE3("# timegm/ cycles: %d, days: %lld, orig_year: %lld\n", cycles, days, orig_year); + + if( orig_year > 70 ) { + year = 70; + while( year < orig_year ) { + days += length_of_year[IS_LEAP(year)]; + year++; + } + } + else if ( orig_year < 70 ) { + year = 69; + do { + days -= length_of_year[IS_LEAP(year)]; + year--; + } while( year >= orig_year ); + } + + + days += julian_days_by_month[IS_LEAP(orig_year)][date->tm_mon]; + days += date->tm_mday - 1; + + seconds = days * 60 * 60 * 24; + + seconds += date->tm_hour * 60 * 60; + seconds += date->tm_min * 60; + seconds += date->tm_sec; + + return(seconds); +} + + +static int check_tm(struct TM *tm) +{ + /* Don't forget leap seconds */ + assert(tm->tm_sec >= 0); + assert(tm->tm_sec <= 61); + + assert(tm->tm_min >= 0); + assert(tm->tm_min <= 59); + + assert(tm->tm_hour >= 0); + assert(tm->tm_hour <= 23); + + assert(tm->tm_mday >= 1); + assert(tm->tm_mday <= days_in_month[IS_LEAP(tm->tm_year)][tm->tm_mon]); + + assert(tm->tm_mon >= 0); + assert(tm->tm_mon <= 11); + + assert(tm->tm_wday >= 0); + assert(tm->tm_wday <= 6); + + assert(tm->tm_yday >= 0); + assert(tm->tm_yday <= length_of_year[IS_LEAP(tm->tm_year)]); + +#ifdef HAS_TM_TM_GMTOFF + assert(tm->tm_gmtoff >= -24 * 60 * 60); + assert(tm->tm_gmtoff <= 24 * 60 * 60); +#endif + + return 1; +} + + +/* The exceptional centuries without leap years cause the cycle to + shift by 16 +*/ +static Year cycle_offset(Year year) +{ + const Year start_year = 2000; + Year year_diff = year - start_year; + Year exceptions; + + if( year > start_year ) + year_diff--; + + exceptions = year_diff / 100; + exceptions -= year_diff / 400; + + TRACE3("# year: %lld, exceptions: %lld, year_diff: %lld\n", + year, exceptions, year_diff); + + return exceptions * 16; +} + +/* For a given year after 2038, pick the latest possible matching + year in the 28 year calendar cycle. + + A matching year... + 1) Starts on the same day of the week. + 2) Has the same leap year status. + + This is so the calendars match up. + + Also the previous year must match. When doing Jan 1st you might + wind up on Dec 31st the previous year when doing a -UTC time zone. + + Finally, the next year must have the same start day of week. This + is for Dec 31st with a +UTC time zone. + It doesn't need the same leap year status since we only care about + January 1st. +*/ +static int safe_year(const Year year) +{ + int safe_year = 0; + Year year_cycle; + + if( year >= MIN_SAFE_YEAR && year <= MAX_SAFE_YEAR ) { + return (int)year; + } + + year_cycle = year + cycle_offset(year); + + /* safe_years_low is off from safe_years_high by 8 years */ + if( year < MIN_SAFE_YEAR ) + year_cycle -= 8; + + /* Change non-leap xx00 years to an equivalent */ + if( is_exception_century(year) ) + year_cycle += 11; + + /* Also xx01 years, since the previous year will be wrong */ + if( is_exception_century(year - 1) ) + year_cycle += 17; + + year_cycle %= SOLAR_CYCLE_LENGTH; + if( year_cycle < 0 ) + year_cycle = SOLAR_CYCLE_LENGTH + year_cycle; + + assert( year_cycle >= 0 ); + assert( year_cycle < SOLAR_CYCLE_LENGTH ); + if( year < MIN_SAFE_YEAR ) + safe_year = safe_years_low[year_cycle]; + else if( year > MAX_SAFE_YEAR ) + safe_year = safe_years_high[year_cycle]; + else + assert(0); + + TRACE3("# year: %lld, year_cycle: %lld, safe_year: %d\n", + year, year_cycle, safe_year); + + assert(safe_year <= MAX_SAFE_YEAR && safe_year >= MIN_SAFE_YEAR); + + return safe_year; +} + + +void copy_tm_to_TM(const struct tm *src, struct TM *dest) { + if( src == NULL ) { + memset(dest, 0, sizeof(*dest)); + } + else { +# ifdef USE_TM64 + dest->tm_sec = src->tm_sec; + dest->tm_min = src->tm_min; + dest->tm_hour = src->tm_hour; + dest->tm_mday = src->tm_mday; + dest->tm_mon = src->tm_mon; + dest->tm_year = (Year)src->tm_year; + dest->tm_wday = src->tm_wday; + dest->tm_yday = src->tm_yday; + dest->tm_isdst = src->tm_isdst; + +# ifdef HAS_TM_TM_GMTOFF + dest->tm_gmtoff = src->tm_gmtoff; +# endif + +# ifdef HAS_TM_TM_ZONE + dest->tm_zone = src->tm_zone; +# endif + +# else + /* They're the same type */ + memcpy(dest, src, sizeof(*dest)); +# endif + } +} + + +void copy_TM_to_tm(const struct TM *src, struct tm *dest) { + if( src == NULL ) { + memset(dest, 0, sizeof(*dest)); + } + else { +# ifdef USE_TM64 + dest->tm_sec = src->tm_sec; + dest->tm_min = src->tm_min; + dest->tm_hour = src->tm_hour; + dest->tm_mday = src->tm_mday; + dest->tm_mon = src->tm_mon; + dest->tm_year = (int)src->tm_year; + dest->tm_wday = src->tm_wday; + dest->tm_yday = src->tm_yday; + dest->tm_isdst = src->tm_isdst; + +# ifdef HAS_TM_TM_GMTOFF + dest->tm_gmtoff = src->tm_gmtoff; +# endif + +# ifdef HAS_TM_TM_ZONE + dest->tm_zone = src->tm_zone; +# endif + +# else + /* They're the same type */ + memcpy(dest, src, sizeof(*dest)); +# endif + } +} + + +/* Simulate localtime_r() to the best of our ability */ +struct tm * fake_localtime_r(const time_t *clock, struct tm *result) { + const struct tm *static_result = localtime(clock); + + assert(result != NULL); + + if( static_result == NULL ) { + memset(result, 0, sizeof(*result)); + return NULL; + } + else { + memcpy(result, static_result, sizeof(*result)); + return result; + } +} + + + +/* Simulate gmtime_r() to the best of our ability */ +struct tm * fake_gmtime_r(const time_t *clock, struct tm *result) { + const struct tm *static_result = gmtime(clock); + + assert(result != NULL); + + if( static_result == NULL ) { + memset(result, 0, sizeof(*result)); + return NULL; + } + else { + memcpy(result, static_result, sizeof(*result)); + return result; + } +} + + +static Time64_T seconds_between_years(Year left_year, Year right_year) { + int increment = (left_year > right_year) ? 1 : -1; + Time64_T seconds = 0; + int cycles; + + if( left_year > 2400 ) { + cycles = (left_year - 2400) / 400; + left_year -= cycles * 400; + seconds += cycles * seconds_in_gregorian_cycle; + } + else if( left_year < 1600 ) { + cycles = (left_year - 1600) / 400; + left_year += cycles * 400; + seconds += cycles * seconds_in_gregorian_cycle; + } + + while( left_year != right_year ) { + seconds += length_of_year[IS_LEAP(right_year - 1900)] * 60 * 60 * 24; + right_year += increment; + } + + return seconds * increment; +} + + +Time64_T mktime64(const struct TM *input_date) { + struct tm safe_date; + struct TM date; + Time64_T time; + Year year = input_date->tm_year + 1900; + + if( MIN_SAFE_YEAR <= year && year <= MAX_SAFE_YEAR ) { + copy_TM_to_tm(input_date, &safe_date); + return (Time64_T)mktime(&safe_date); + } + + /* Have to make the year safe in date else it won't fit in safe_date */ + date = *input_date; + date.tm_year = safe_year(year) - 1900; + copy_TM_to_tm(&date, &safe_date); + + time = (Time64_T)mktime(&safe_date); + + time += seconds_between_years(year, (Year)(safe_date.tm_year + 1900)); + + return time; +} + + +/* Because I think mktime() is a crappy name */ +Time64_T timelocal64(const struct TM *date) { + return mktime64(date); +} + + +struct TM *gmtime64_r (const Time64_T *in_time, struct TM *p) +{ + int v_tm_sec, v_tm_min, v_tm_hour, v_tm_mon, v_tm_wday; + Time64_T v_tm_tday; + int leap; + Time64_T m; + Time64_T time = *in_time; + Year year = 70; + int cycles = 0; + + assert(p != NULL); + + /* Use the system gmtime() if time_t is small enough */ + if( SHOULD_USE_SYSTEM_GMTIME(*in_time) ) { + time_t safe_time = *in_time; + struct tm safe_date; + GMTIME_R(&safe_time, &safe_date); + + copy_tm_to_TM(&safe_date, p); + assert(check_tm(p)); + + return p; + } + +#ifdef HAS_TM_TM_GMTOFF + p->tm_gmtoff = 0; +#endif + p->tm_isdst = 0; + +#ifdef HAS_TM_TM_ZONE + p->tm_zone = "UTC"; +#endif + + v_tm_sec = (int)(time % 60); + time /= 60; + v_tm_min = (int)(time % 60); + time /= 60; + v_tm_hour = (int)(time % 24); + time /= 24; + v_tm_tday = time; + + WRAP (v_tm_sec, v_tm_min, 60); + WRAP (v_tm_min, v_tm_hour, 60); + WRAP (v_tm_hour, v_tm_tday, 24); + + v_tm_wday = (int)((v_tm_tday + 4) % 7); + if (v_tm_wday < 0) + v_tm_wday += 7; + m = v_tm_tday; + + if (m >= CHEAT_DAYS) { + year = CHEAT_YEARS; + m -= CHEAT_DAYS; + } + + if (m >= 0) { + /* Gregorian cycles, this is huge optimization for distant times */ + cycles = (int)(m / (Time64_T) days_in_gregorian_cycle); + if( cycles ) { + m -= (cycles * (Time64_T) days_in_gregorian_cycle); + year += (cycles * years_in_gregorian_cycle); + } + + /* Years */ + leap = IS_LEAP (year); + while (m >= (Time64_T) length_of_year[leap]) { + m -= (Time64_T) length_of_year[leap]; + year++; + leap = IS_LEAP (year); + } + + /* Months */ + v_tm_mon = 0; + while (m >= (Time64_T) days_in_month[leap][v_tm_mon]) { + m -= (Time64_T) days_in_month[leap][v_tm_mon]; + v_tm_mon++; + } + } else { + year--; + + /* Gregorian cycles */ + cycles = (int)((m / (Time64_T) days_in_gregorian_cycle) + 1); + if( cycles ) { + m -= (cycles * (Time64_T) days_in_gregorian_cycle); + year += (cycles * years_in_gregorian_cycle); + } + + /* Years */ + leap = IS_LEAP (year); + while (m < (Time64_T) -length_of_year[leap]) { + m += (Time64_T) length_of_year[leap]; + year--; + leap = IS_LEAP (year); + } + + /* Months */ + v_tm_mon = 11; + while (m < (Time64_T) -days_in_month[leap][v_tm_mon]) { + m += (Time64_T) days_in_month[leap][v_tm_mon]; + v_tm_mon--; + } + m += (Time64_T) days_in_month[leap][v_tm_mon]; + } + + p->tm_year = year; + if( p->tm_year != year ) { +#ifdef EOVERFLOW + errno = EOVERFLOW; +#endif + return NULL; + } + + /* At this point m is less than a year so casting to an int is safe */ + p->tm_mday = (int) m + 1; + p->tm_yday = julian_days_by_month[leap][v_tm_mon] + (int)m; + p->tm_sec = v_tm_sec; + p->tm_min = v_tm_min; + p->tm_hour = v_tm_hour; + p->tm_mon = v_tm_mon; + p->tm_wday = v_tm_wday; + + assert(check_tm(p)); + + return p; +} + + +struct TM *localtime64_r (const Time64_T *time, struct TM *local_tm) +{ + time_t safe_time; + struct tm safe_date; + struct TM gm_tm; + Year orig_year; + int month_diff; + + assert(local_tm != NULL); + + /* Use the system localtime() if time_t is small enough */ + if( SHOULD_USE_SYSTEM_LOCALTIME(*time) ) { + safe_time = *time; + + TRACE1("Using system localtime for %lld\n", *time); + + LOCALTIME_R(&safe_time, &safe_date); + + copy_tm_to_TM(&safe_date, local_tm); + assert(check_tm(local_tm)); + + return local_tm; + } + + if( gmtime64_r(time, &gm_tm) == NULL ) { + TRACE1("gmtime64_r returned null for %lld\n", *time); + return NULL; + } + + orig_year = gm_tm.tm_year; + + if (gm_tm.tm_year > (2037 - 1900) || + gm_tm.tm_year < (1970 - 1900) + ) + { + TRACE1("Mapping tm_year %lld to safe_year\n", (Year)gm_tm.tm_year); + gm_tm.tm_year = safe_year((Year)(gm_tm.tm_year + 1900)) - 1900; + } + + safe_time = timegm64(&gm_tm); + if( LOCALTIME_R(&safe_time, &safe_date) == NULL ) { + TRACE1("localtime_r(%d) returned NULL\n", (int)safe_time); + return NULL; + } + + copy_tm_to_TM(&safe_date, local_tm); + + local_tm->tm_year = orig_year; + if( local_tm->tm_year != orig_year ) { + TRACE2("tm_year overflow: tm_year %lld, orig_year %lld\n", + (Year)local_tm->tm_year, (Year)orig_year); + +#ifdef EOVERFLOW + errno = EOVERFLOW; +#endif + return NULL; + } + + + month_diff = local_tm->tm_mon - gm_tm.tm_mon; + + /* When localtime is Dec 31st previous year and + gmtime is Jan 1st next year. + */ + if( month_diff == 11 ) { + local_tm->tm_year--; + } + + /* When localtime is Jan 1st, next year and + gmtime is Dec 31st, previous year. + */ + if( month_diff == -11 ) { + local_tm->tm_year++; + } + + /* GMT is Jan 1st, xx01 year, but localtime is still Dec 31st + in a non-leap xx00. There is one point in the cycle + we can't account for which the safe xx00 year is a leap + year. So we need to correct for Dec 31st comming out as + the 366th day of the year. + */ + if( !IS_LEAP(local_tm->tm_year) && local_tm->tm_yday == 365 ) + local_tm->tm_yday--; + + assert(check_tm(local_tm)); + + return local_tm; +} + + +int valid_tm_wday( const struct TM* date ) { + if( 0 <= date->tm_wday && date->tm_wday <= 6 ) + return 1; + else + return 0; +} + +int valid_tm_mon( const struct TM* date ) { + if( 0 <= date->tm_mon && date->tm_mon <= 11 ) + return 1; + else + return 0; +} + + +char *asctime64_r( const struct TM* date, char *result ) { + /* I figure everything else can be displayed, even hour 25, but if + these are out of range we walk off the name arrays */ + if( !valid_tm_wday(date) || !valid_tm_mon(date) ) + return NULL; + + sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n", + wday_name[date->tm_wday], + mon_name[date->tm_mon], + date->tm_mday, date->tm_hour, + date->tm_min, date->tm_sec, + 1900 + date->tm_year); + + return result; +} + + +char *ctime64_r( const Time64_T* time, char* result ) { + struct TM date; + + localtime64_r( time, &date ); + return asctime64_r( &date, result ); +} + + +/* Non-thread safe versions of the above */ +struct TM *localtime64(const Time64_T *time) { + return localtime64_r(time, &Static_Return_Date); +} + +struct TM *gmtime64(const Time64_T *time) { + return gmtime64_r(time, &Static_Return_Date); +} + +char *asctime64( const struct TM* date ) { + return asctime64_r( date, Static_Return_String ); +} + +char *ctime64( const Time64_T* time ) { + return asctime64(localtime64(time)); +} diff --git a/libc/bionic/time64_config.h b/libc/bionic/time64_config.h new file mode 100644 index 0000000..53bcecf --- /dev/null +++ b/libc/bionic/time64_config.h @@ -0,0 +1,75 @@ +/* Debugging + TIME_64_DEBUG + Define if you want debugging messages +*/ +/* #define TIME_64_DEBUG */ + + +/* INT_64_T + A 64 bit integer type to use to store time and others. + Must be defined. +*/ +#define INT_64_T long long + + +/* USE_TM64 + Should we use a 64 bit safe replacement for tm? This will + let you go past year 2 billion but the struct will be incompatible + with tm. Conversion functions will be provided. +*/ +/* #define USE_TM64 */ + + +/* Availability of system functions. + + HAS_GMTIME_R + Define if your system has gmtime_r() + + HAS_LOCALTIME_R + Define if your system has localtime_r() + + HAS_TIMEGM + Define if your system has timegm(), a GNU extension. +*/ +#define HAS_GMTIME_R +#define HAS_LOCALTIME_R +/*#define HAS_TIMEGM */ + + +/* Details of non-standard tm struct elements. + + HAS_TM_TM_GMTOFF + True if your tm struct has a "tm_gmtoff" element. + A BSD extension. + + HAS_TM_TM_ZONE + True if your tm struct has a "tm_zone" element. + A BSD extension. +*/ +#define HAS_TM_TM_GMTOFF +#define HAS_TM_TM_ZONE + + +/* USE_SYSTEM_LOCALTIME + USE_SYSTEM_GMTIME + Should we use the system functions if the time is inside their range? + Your system localtime() is probably more accurate, but our gmtime() is + fast and safe. +*/ +#define USE_SYSTEM_LOCALTIME +/* #define USE_SYSTEM_GMTIME */ + + +/* SYSTEM_LOCALTIME_MAX + SYSTEM_LOCALTIME_MIN + SYSTEM_GMTIME_MAX + SYSTEM_GMTIME_MIN + Maximum and minimum values your system's gmtime() and localtime() + can handle. We will use your system functions if the time falls + inside these ranges. +*/ +#define SYSTEM_LOCALTIME_MAX 2147483647 +#define SYSTEM_LOCALTIME_MIN -2147483647 +#define SYSTEM_GMTIME_MAX 2147483647 +#define SYSTEM_GMTIME_MIN -2147483647 + diff --git a/libc/docs/OVERVIEW.TXT b/libc/docs/OVERVIEW.TXT new file mode 100644 index 0000000..4d40df6 --- /dev/null +++ b/libc/docs/OVERVIEW.TXT @@ -0,0 +1,364 @@ +Bionic C Library Overview: +========================== + +Introduction: + +Core Philosophy: + + The core idea behind Bionic's design is: KEEP IT REALLY SIMPLE. + + This implies that the C library should only provide lightweight wrappers around kernel + facilities and not try to be too smart to deal with edge cases. + + The name "Bionic" comes from the fact that it is part-BSD and part-Linux: its source + code consists in a mix of BSD C library pieces with custom Linux-specific bits used + to deal with threads, processes, signals and a few others things. + + All original BSD pieces carry the BSD copyright disclaimer. Bionic-specific bits + carry the Android Open Source Project copyright disclaimer. And everything is released + under the BSD license. + +Architectures: + + Bionic currently supports the ARM and x86 instruction sets. In theory, it should be + possible to support more, but this may require a little work (e.g. adding system + call IDs to SYSCALLS.TXT, described below, or modifying the dynamic linker). + + The ARM-specific code is under arch-arm/ and the x86-specific one is under arch-x86/ + + Note that the x86 version is only meant to run on an x86 Android device. We make + absolutely no claim that you could build and use Bionic on a stock x86 Linux + distribution (though that would be cool, so patches are welcomed :-)) + +Syscall stubs: + + Each system call function is implemented by a tiny assembler source fragment + (called a "syscall stub"), which is generated automatically by tools/gensyscalls.py + which reads the SYSCALLS.TXT file for input. + + SYSCALLS.TXT contains the list of all syscall stubs to generate, along with + the corresponding syscall numeric identifier (which may differ between ARM and x86), + and its signature + + If you modify this file, you may want to use tools/checksyscalls.py which checks + its content against official Linux kernel header files, and will report errors when + invalid syscall ids are used. + + Sometimes, the C library function is really a wrapper that calls the corresponding + syscall with another name. For example, the exit() function is provided by the C + library and calls the _exit() syscall stub. + + See SYSCALLS.TXT for documentation and details. + + +time_t: + + time_t is 32-bit as defined by the kernel on 32-bit CPUs. A 64-bit version would + be preferrable to avoid the Y2038 bug, but the kernel maintainers consider that + this is not needed at the moment. + + Instead, Bionic provides a <time64.h> header that defines a time64_t type, and + related functions like mktime64(), localtime64(), etc... + + +Timezone management: + + The name of the current timezone is taken from the TZ environment variable, if defined. + Otherwise, the system property named 'persist.sys.timezone' is checked instead. + + The zoneinfo timezone database and index files are located under directory + /system/usr/share/zoneinfo, instead of the more Posix path of /usr/share/zoneinfo + + +off_t: + + For similar reasons, off_t is 32-bit. We define loff_t as the 64-bit variant due + to BSD inheritance, but off64_t should be available as a typedef to ease porting of + current Linux-specific code. + + + +Linux kernel headers: + + Bionic comes with its own set of "clean" Linux kernel headers to allow user-space + code to use kernel-specific declarations (e.g. IOCTLs, structure declarations, + constants, etc...). They are located in: + + ./kernel/common, + ./kernel/arch-arm + ./kernel/arch-x86 + + These headers have been generated by a tool (kernel/tools/update-all.py) to only + include the public definitions from the original Linux kernel headers. + + If you want to know why and how this is done, read kernel/README.TXT to get + all the (gory) details. + + +PThread implementation: + + Bionic's C library comes with its own pthread implementation bundled in. This is + different from other historical C libraries which: + + - place it in an external library (-lpthread) + - play linker tricks with weak symbols at dynamic link time + + The support for real-time features (a.k.a. -lrt) is also bundled in the C library. + + The implementation is based on futexes and strives to provide *very* short code paths + for common operations. Notable features are the following: + + - pthread_mutex_t, pthread_cond_t are only 4 bytes each. + + - Normal, recursive and error-check mutexes are supported, and the code path + is heavily optimized for the normal case, which is used most of the time. + + - Process-shared mutexes and condition variables are not supported. + Their implementation requires far more complexity and was absolutely + not needed for Android (which uses other inter-process synchronization + capabilities). + + Note that they could be added in the future without breaking the ABI + by specifying more sophisticated code paths (which may make the common + paths slightly slower though). + + - There is currently no support for read/write locks, priority-ceiling in + mutexes and other more advanced features. Again, the main idea being that + this was not needed for Android at all but could be added in the future. + +pthread_cancel(): + + pthread_cancel() will *not* be supported in Bionic, because doing this would + involve making the C library significantly bigger for very little benefit. + + Consider that: + + - A proper implementation must insert pthread cancellation checks in a lot + of different places of the C library. And conformance is very difficult to + test properly. + + - A proper implementation must also clean up resources, like releasing memory, + or unlocking mutexes, properly if the cancellation happens in a complex + function (e.g. inside gethostbyname() or fprintf() + complex formatting + rules). This tends to slow down the path of many functions. + + - pthread cancellation cannot stop all threads: e.g. it can't do anything + against an infinite loop + + - pthread cancellation itself has short-comings and isn't very portable + (see http://advogato.org/person/slamb/diary.html?start=49 for example). + + All of this is contrary to the Bionic design goals. If your code depends on + thread cancellation, please consider alternatives. + + Note however that Bionic does implement pthread_cleanup_push() and pthread_cleanup_pop(), + which can be used to handle cleanups that happen when a thread voluntarily exits + through pthread_exit() or returning from its main function. + + +pthread_once(): + + Do not call fork() within a callback provided to pthread_once(). Doing this + may result in a deadlock in the child process the next time it calls pthread_once(). + + Also, you can't throw a C++ Exception from the callback (see C++ Exception Support + below). + + The current implementation of pthread_once() lacks the necessary support of + multi-core-safe double-checked-locking (read and write barriers). + + +Thread-specific data + + The thread-specific storage only provides for a bit less than 64 pthread_key_t + objects to each process. The implementation provides 64 real slots but also + uses about 5 of them (exact number may depend on implementation) for its + own use (e.g. two slots are pre-allocated by the C library to speed-up the + Android OpenGL sub-system). + + Note that Posix mandates a minimum of 128 slots, but we do not claim to be + Posix-compliant. + + Except for the main thread, the TLS area is stored at the top of the stack. See + comments in bionic/libc/bionic/pthread.c for details. + + At the moment, thread-local storage defined through the __thread compiler keyword + is not supported by the Bionic C library and dynamic linker. + + +Multi-core support + + At the moment, Bionic does not provide or use read/write memory barriers. + This means that using it on certain multi-core systems might not be supported, + depending on its exact CPU architecture. + + +Android-specific features: + + Bionic provides a small number of Android-specific features to its clients: + + - access to system properties: + + Android provides a simple shared value/key space to all processes on the + system. It stores a liberal number of 'properties', each of them being a + simple size-limited string that can be associated to a size-limited string + value. + + The header <sys/system_properties.h> can be used to read system properties + and also defines the maximum size of keys and values. + + - Android-specific user/group management: + + There is no /etc/passwd or /etc/groups in Android. By design, it is meant to + be used by a single handset user. On the other hand, Android uses the Linux + user/group management features extensively to secure process permissions, + like access to various filesystem directories. + + In the Android scheme, each installed application gets its own uid_t/gid_t + starting from 10000; lower numerical ids are reserved for system daemons. + + getpwnam() recognizes some hard-coded subsystems names (e.g. "radio") and + will translate them to their low-user-id values. It also recognizes "app_1234" + as the synthetic name of the application that was installed with uid 10000 + 1234, + which is 11234. getgrnam() works similarly + + getgrouplist() will always return a single group for any user name, which is + the one passed as an input parameter. + + getgrgid() will similarly only return a structure that contains a single-element + members list, corresponding to the user with the same numerical value than the + group. + + See bionic/libc/bionic/stubs.c for more details. + + - getservent() + + There is no /etc/services on Android. Instead the C library embeds a constant + list of services in its executable, which is parsed on demand by the various + functions that depend on it. See bionic/libc/netbsd/net/getservent.c and + bionic/libc/netbsd/net/services.h + + The list of services defined internally might change liberally in the future. + This feature is mostly historically and is very rarely used. + + The getservent() returns thread-local data. getservbyport() and getservbyname() + are also implemented in a similar fashion. + + - getprotoent() + + There is no /etc/protocol on Android. Bionic does not currently implement + getprotoent() and related functions. If we add it, it will likely be done + in a way similar to getservent() + +DNS resolver: + + Bionic uses a NetBSD-derived resolver library which has been modified in the following + ways: + + - don't implement the name-server-switch feature (a.k.a. <nsswitch.h>) + + - read /system/etc/resolv.conf instead of /etc/resolv.conf + + - read the list of servers from system properties. the code looks for + 'net.dns1', 'net.dns2', etc.. Each property should contain the IP address + of a DNS server. + + these properties are set/modified by other parts of the Android system + (e.g. the dhcpd daemon). + + the implementation also supports per-process DNS server list, using the + properties 'net.dns1.<pid>', 'net.dns2.<pid>', etc... Where <pid> stands + for the numerical ID of the current process. + + - when performing a query, use a properly randomized Query ID (instead of + a incremented one), for increased security. + + - when performing a query, bind the local client socket to a random port + for increased security. + + - get rid of *many* unfortunate thread-safety issues in the original code + + Bionic does *not* expose implementation details of its DNS resolver; the content + of <arpa/nameser.h> is intentionally blank. The resolver implementation might + change completely in the future. + + +PThread Real-Time Timers: + + timer_create(), timer_gettime(), timer_settime() and timer_getoverrun() are + supported. + + Bionic also now supports SIGEV_THREAD real-time timers (see timer_create()). + The implementation simply uses a single thread per timer, unlike GLibc which + uses complex heuristics to try to use the less threads possible when several + timers with compatible properties are used. + + This means that if your code uses a lot of SIGEV_THREAD timers, your program + may consume a lot of memory. However, if your program needs many of these timers, + it'd better handle timeout events directly instead. + + Other timers (e.g. SIGEV_SIGNAL) are handled by the kernel and use much less + system resources. + + +Binary Compatibility: + + Bionic is *not* in any way binary-compatible with the GNU C Library, ucLibc or any + known Linux C library. This means several things: + + - You cannot expect to build something against the GNU C Library headers and have + it dynamically link properly to Bionic later. + + - You should *really* use the Android toolchain to build your program against Bionic. + The toolchain deals with many important details that are crucial to get something + working properly. + + Failure to do so will usually result in the inability to run or link your program, + or even runtime crashes. Several random web pages on the Internet describe how you + can succesfully write a "hello-world" program with the ARM GNU toolchain. These + examples usually work by chance, if anything else, and you should not follow these + instructions unless you want to waste a lot of your time in the process. + + Note however that you *can* generate a binary that is built against the GNU C Library + headers and then statically linked to it. The corresponding executable should be able + to run (if it doesn't use dlopen()/dlsym()) + +Dynamic Linker: + + Bionic comes with its own dynamic linker (just like ld.so on Linux really comes from + GLibc). This linker does not support all the relocations generated by other GCC ARM + toolchains. + +C++ Exceptions Support: + + At the moment, Bionic doesn't support C++ exceptions, what this really means is the + following: + + - If pthread_once() is called with a C++ callback that throws an exception, + then the C library will keep the corresponding pthread_once_t mutex locked. + Any further call to pthread_once() will result in a deadlock. + + A proper implementation should be able to register a C++ exception cleanup + handler before the callback to properly unlock the pthread_once_t. Unfortunately + this requires tricky assembly code that is highly dependent on the compiler. + + This feature is not planned to be supported anytime soon. + + - The same problem may arise if you throw an exception within a callback called + from the C library. Fortunately, these cases are very rare in the real-world, + but any callback you provide to the C library should *not* throw an exception. + + - Bionic lacks a few support functions to have exception support work properly. + +Include Paths: + + The Android build system should automatically provide the necessary include paths + required to build against the C library headers. However, if you want to do that + yourself, you will need to add: + + libc/arch-$ARCH/include + libc/include + libc/kernel/common + libc/kernel/arch-$ARCH + + to your C include path. diff --git a/libc/include/pthread.h b/libc/include/pthread.h index 9c40099..e3afdae 100644 --- a/libc/include/pthread.h +++ b/libc/include/pthread.h @@ -97,6 +97,9 @@ typedef volatile int pthread_once_t; #define PTHREAD_PROCESS_PRIVATE 0 #define PTHREAD_PROCESS_SHARED 1 +#define PTHREAD_SCOPE_SYSTEM 0 +#define PTHREAD_SCOPE_PROCESS 1 + /* * Prototypes */ @@ -128,6 +131,9 @@ int pthread_attr_getstack(pthread_attr_t const * attr, void ** stackaddr, size_t int pthread_attr_setguardsize(pthread_attr_t * attr, size_t guard_size); int pthread_attr_getguardsize(pthread_attr_t const * attr, size_t * guard_size); +int pthread_attr_setscope(pthread_attr_t *attr, int scope); +int pthread_attr_getscope(pthread_attr_t const *attr); + int pthread_getattr_np(pthread_t thid, pthread_attr_t * attr); int pthread_create(pthread_t *thread, pthread_attr_t const * attr, diff --git a/libc/include/string.h b/libc/include/string.h index 435923b..613dcd7 100644 --- a/libc/include/string.h +++ b/libc/include/string.h @@ -82,9 +82,8 @@ extern size_t strspn(const char *, const char *); extern char* strsignal(int sig); -/* Just declared to make libstdc++-v3 happy. */ -extern int strcoll (const char *, const char *); -extern size_t strxfrm (char *, const char *, size_t); +extern int strcoll(const char *, const char *); +extern size_t strxfrm(char *, const char *, size_t); __END_DECLS diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h index 5e6363f..23ab5ae 100644 --- a/libc/include/sys/stat.h +++ b/libc/include/sys/stat.h @@ -71,6 +71,10 @@ struct stat { unsigned long long st_ino; }; +extern int chmod(const char *, mode_t); +extern int fchmod(int, mode_t); +extern int mkdir(const char *, mode_t); + extern int stat(const char *, struct stat *); extern int fstat(int, struct stat *); extern int lstat(const char *, struct stat *); diff --git a/libc/include/sys/time.h b/libc/include/sys/time.h index 4dee4da..1f010d4 100644 --- a/libc/include/sys/time.h +++ b/libc/include/sys/time.h @@ -56,7 +56,7 @@ extern int utimes(const char *, const struct timeval *); #define timeradd(a, b, res) \ do { \ (res)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ - (res)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ + (res)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ if ((res)->tv_usec >= 1000000) { \ (res)->tv_usec -= 1000000; \ (res)->tv_sec += 1; \ diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h index 92b452c..b071ee9 100644 --- a/libc/include/sys/types.h +++ b/libc/include/sys/types.h @@ -65,6 +65,7 @@ typedef __kernel_nlink_t nlink_t; #define _OFF_T_DEFINED_ typedef __kernel_off_t off_t; typedef __kernel_loff_t loff_t; +typedef loff_t off64_t; /* GLibc-specific */ typedef __kernel_pid_t pid_t; diff --git a/libc/include/time64.h b/libc/include/time64.h new file mode 100644 index 0000000..9da4bc7 --- /dev/null +++ b/libc/include/time64.h @@ -0,0 +1,54 @@ +/* + +Copyright (c) 2007-2008 Michael G Schwern + +This software originally derived from Paul Sheer's pivotal_gmtime_r.c. + +The MIT License: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Origin: http://code.google.com/p/y2038 +Modified for Bionic by the Android Open Source Project + +*/ +#ifndef TIME64_H +#define TIME64_H + +#include <time.h> +#include <stdint.h> + +typedef int64_t time64_t; + +struct tm *gmtime64_r (const time64_t *, struct tm *); +struct tm *localtime64_r (const time64_t *, struct tm *); +struct tm *gmtime64 (const time64_t *); +struct tm *localtime64 (const time64_t *); + +char *asctime64 (const struct tm *); +char *asctime64_r (const struct tm *, char *); + +char *ctime64 (const time64_t*); +char *ctime64_r (const time64_t*, char*); + +time64_t timegm64 (const struct tm *); +time64_t mktime64 (const struct tm *); +time64_t timelocal64 (const struct tm *); + +#endif /* TIME64_H */ diff --git a/libc/include/unistd.h b/libc/include/unistd.h index b6d70cc..1ada37e 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -34,6 +34,7 @@ #include <sys/select.h> #include <sys/sysconf.h> #include <linux/capability.h> +#include <pathconf.h> __BEGIN_DECLS @@ -111,9 +112,6 @@ extern int link(const char *, const char *); extern int unlink(const char *); extern int chdir(const char *); extern int fchdir(int); -extern int chmod(const char *, mode_t); -extern int fchmod(int, mode_t); -extern int mkdir(const char *, mode_t); extern int rmdir(const char *); extern int pipe(int *); extern int chroot(const char *); diff --git a/libc/string/strcoll.c b/libc/string/strcoll.c new file mode 100755 index 0000000..365cad5 --- /dev/null +++ b/libc/string/strcoll.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include <string.h> + +/* + * Compare strings using the current locale. Since Bionic really does not + * support locales, we assume we always use the C locale and call strcmp. + * + * This function is provided to make libstdc++-v3 usable. + */ +int +strcoll(const char *s1, const char *s2) +{ + return strcmp (s1, s2); +} diff --git a/libc/string/strxfrm.c b/libc/string/strxfrm.c new file mode 100755 index 0000000..f1843b5 --- /dev/null +++ b/libc/string/strxfrm.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include <string.h> + +/* + * Transform string s2 to string s1 using the current locale so that + * strcmp of transformed strings yields the same result as strcoll. + * Since Bionic really does not support locales, we assume we always use + * the C locale. + * + * This function is provided to make libstdc++-v3 usable. + */ +size_t +strxfrm(char *s1, const char *s2, size_t n) +{ + size_t len = strlen(s2) + 1; + + if (len < n) + n = len; + memcpy(s1, s2, n); + return len; +} diff --git a/libdl/dltest.c b/libdl/dltest.c index e84d5a3..14cd854 100755 --- a/libdl/dltest.c +++ b/libdl/dltest.c @@ -1,119 +1,147 @@ -#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <string.h>
-#include <dlfcn.h>
-
-extern char *optarg;
-extern int optind, opterr, optopt;
-
-static struct option long_options[] = {
- {"library", required_argument, 0, 'l'},
- {"symbol", required_argument, 0, 's'},
- {"help", no_argument, 0, 'h'},
- {0, 0, 0, 0},
-};
-
-/* This array must parallel long_options[] */
-static const char *descriptions[] = {
- "specify a library path to look up symbol",
- "specify symbol to look up",
- "print this help screen",
-};
-
-void print_help(const char *name) {
- fprintf(stdout,
- "invokation:\n"
- "\t%s [-l <libname>] -s <symbol name>\n"
- "\t%s -h\n\n", name, name);
- fprintf(stdout, "options:\n");
- struct option *opt = long_options;
- const char **desc = descriptions;
- while (opt->name) {
- fprintf(stdout, "\t-%c/--%s%s: %s\n",
- opt->val,
- opt->name,
- (opt->has_arg ? " (argument)" : ""),
- *desc);
- opt++;
- desc++;
- }
-}
-
-int get_options(int argc, char **argv, char **lib, char **sym)
-{
- int c;
-
- *lib = 0;
- *sym = 0;
-
- while (1) {
- /* getopt_long stores the option index here. */
- int option_index = 0;
-
- c = getopt_long (argc, argv,
- "l:s:h",
- long_options,
- &option_index);
- /* Detect the end of the options. */
- if (c == -1) break;
-
- switch (c) {
- case 'l':
- *lib = strdup(optarg);
- break;
- case 's':
- *sym = strdup(optarg);
- break;
- case 'h': print_help(argv[0]); exit(EXIT_FAILURE); break;
- case '?':
- /* getopt_long already printed an error message. */
- break;
- default:
- fprintf(stderr, "Unknown option");
- exit(EXIT_FAILURE);
- }
- }
-
- return optind;
-}
-
-int main(int argc, char **argv)
-{
- char *libname, *symname, *prog = *argv;
-
- get_options(argc, argv, &libname, &symname);
-
- if (symname == NULL) {
- fprintf(stderr, "You must specify a symbol!\n");
- print_help(prog);
- exit(EXIT_FAILURE);
- }
-
- {
- const char *dlerr;
- void *handle, *symbol;
-
- printf("opening library [%s]\n", libname);
- dlerr = dlerror();
- handle = libname ? dlopen(libname, RTLD_NOW) : RTLD_DEFAULT;
- dlerr = dlerror();
- if (dlerr != NULL) fprintf(stderr, "dlopen() error: %s\n", dlerr);
-
- printf("opening symbol [%s]\n", symname);
- symbol = dlsym(handle, symname);
- dlerr = dlerror();
- if (dlerr != NULL) fprintf(stderr, "dlsym() error: %s\n", dlerr);
-
- printf("closing library [%s]\n", libname);
- dlclose(handle);
- dlerr = dlerror();
- if (dlerr != NULL) fprintf(stderr, "dlclose() error: %s\n", dlerr);
- else printf("successfully opened symbol\n");
- }
-
- if (libname != NULL) free(libname);
- if (symname != NULL) free(symname);
- return 0;
-}
+/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <getopt.h> +#include <string.h> +#include <dlfcn.h> + +extern char *optarg; +extern int optind, opterr, optopt; + +static struct option long_options[] = { + {"library", required_argument, 0, 'l'}, + {"symbol", required_argument, 0, 's'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0}, +}; + +/* This array must parallel long_options[] */ +static const char *descriptions[] = { + "specify a library path to look up symbol", + "specify symbol to look up", + "print this help screen", +}; + +void print_help(const char *name) { + fprintf(stdout, + "invokation:\n" + "\t%s [-l <libname>] -s <symbol name>\n" + "\t%s -h\n\n", name, name); + fprintf(stdout, "options:\n"); + struct option *opt = long_options; + const char **desc = descriptions; + while (opt->name) { + fprintf(stdout, "\t-%c/--%s%s: %s\n", + opt->val, + opt->name, + (opt->has_arg ? " (argument)" : ""), + *desc); + opt++; + desc++; + } +} + +int get_options(int argc, char **argv, char **lib, char **sym) +{ + int c; + + *lib = 0; + *sym = 0; + + while (1) { + /* getopt_long stores the option index here. */ + int option_index = 0; + + c = getopt_long (argc, argv, + "l:s:h", + long_options, + &option_index); + /* Detect the end of the options. */ + if (c == -1) break; + + switch (c) { + case 'l': + *lib = strdup(optarg); + break; + case 's': + *sym = strdup(optarg); + break; + case 'h': print_help(argv[0]); exit(EXIT_FAILURE); break; + case '?': + /* getopt_long already printed an error message. */ + break; + default: + fprintf(stderr, "Unknown option"); + exit(EXIT_FAILURE); + } + } + + return optind; +} + +int main(int argc, char **argv) +{ + char *libname, *symname, *prog = *argv; + + get_options(argc, argv, &libname, &symname); + + if (symname == NULL) { + fprintf(stderr, "You must specify a symbol!\n"); + print_help(prog); + exit(EXIT_FAILURE); + } + + { + const char *dlerr; + void *handle, *symbol; + + printf("opening library [%s]\n", libname); + dlerr = dlerror(); + handle = libname ? dlopen(libname, RTLD_NOW) : RTLD_DEFAULT; + dlerr = dlerror(); + if (dlerr != NULL) fprintf(stderr, "dlopen() error: %s\n", dlerr); + + printf("opening symbol [%s]\n", symname); + symbol = dlsym(handle, symname); + dlerr = dlerror(); + if (dlerr != NULL) fprintf(stderr, "dlsym() error: %s\n", dlerr); + + printf("closing library [%s]\n", libname); + dlclose(handle); + dlerr = dlerror(); + if (dlerr != NULL) fprintf(stderr, "dlclose() error: %s\n", dlerr); + else printf("successfully opened symbol\n"); + } + + if (libname != NULL) free(libname); + if (symname != NULL) free(symname); + return 0; +} diff --git a/linker/arch/arm/begin.S b/linker/arch/arm/begin.S index f9b3bac..e259902 100644 --- a/linker/arch/arm/begin.S +++ b/linker/arch/arm/begin.S @@ -1,3 +1,31 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + .text .align 4 .type _start,#function diff --git a/linker/arch/x86/begin.S b/linker/arch/x86/begin.S index 8f468e6..d8a39ca 100644 --- a/linker/arch/x86/begin.S +++ b/linker/arch/x86/begin.S @@ -1,3 +1,31 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + .text .align 4 .type _start, @function @@ -21,3 +49,4 @@ _start: __CTOR_LIST__: .long -1 + diff --git a/linker/debugger.c b/linker/debugger.c index 542cf8d..5bb065c 100644 --- a/linker/debugger.c +++ b/linker/debugger.c @@ -1,3 +1,31 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -21,7 +49,7 @@ void debugger_signal_handler(int n) signal(SIGUSR1, SIG_IGN); tid = gettid(); - s = socket_local_client("android:debuggerd", + s = socket_local_client("android:debuggerd", ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); if(s >= 0) { @@ -49,4 +77,5 @@ void debugger_init() signal(SIGFPE, debugger_signal_handler); signal(SIGSEGV, debugger_signal_handler); signal(SIGSTKFLT, debugger_signal_handler); + signal(SIGPIPE, debugger_signal_handler); } diff --git a/linker/linker.c b/linker/linker.c index 8f15f62..572f1d6 100644 --- a/linker/linker.c +++ b/linker/linker.c @@ -1,3 +1,31 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include <linux/auxvec.h> #include <stdio.h> diff --git a/linker/linker.h b/linker/linker.h index ab2c385..3ad5104 100644 --- a/linker/linker.h +++ b/linker/linker.h @@ -1,3 +1,31 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #ifndef _LINKER_H_ #define _LINKER_H_ diff --git a/linker/linker_debug.h b/linker/linker_debug.h index fa2a1a1..6e396fd 100644 --- a/linker/linker_debug.h +++ b/linker/linker_debug.h @@ -1,3 +1,31 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #ifndef _LINKER_DEBUG_H_ #define _LINKER_DEBUG_H_ diff --git a/linker/rt.c b/linker/rt.c index d0802ce..30d5a48 100644 --- a/linker/rt.c +++ b/linker/rt.c @@ -1,4 +1,32 @@ /* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* * This function is an empty stub where GDB locates a breakpoint to get notified * about linker activity. */ |