auto import from //branches/cupcake/...@130745

This commit is contained in:
The Android Open Source Project 2009-02-10 15:43:56 -08:00
parent d37527501c
commit 9f65adf2ba
24 changed files with 1883 additions and 186 deletions

View File

@ -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 \

View File

@ -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;

View File

@ -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

View File

@ -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,10 +168,92 @@ static struct group *android_name_to_group(
return android_iinfo_to_group(gr, iinfo + n);
}
}
return NULL;
}
/* 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 )
{
unsigned long id;
char* end;
if (memcmp(name, "app_", 4) != 0 || !isdigit(name[4]))
goto FAIL;
id = strtoul(name+4, &end, 10);
if (id == 0 || *end != '\0')
goto FAIL;
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;
}
struct passwd* getpwuid(uid_t uid)
/* 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;
return NULL;
}
snprintf( state->app_name_buffer, sizeof state->app_name_buffer,
"app_%u", uid - AID_APP );
pw->pw_name = state->app_name_buffer;
pw->pw_dir = "/data";
pw->pw_shell = "/system/bin/sh";
pw->pw_uid = uid;
pw->pw_gid = uid;
return pw;
}
/* 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;
@ -181,35 +266,27 @@ struct passwd* getpwuid(uid_t uid)
if ( android_id_to_passwd(pw, uid) != NULL )
return pw;
if (uid < AID_APP) {
errno = ENOENT;
return NULL;
}
snprintf( state->app_name_buffer, sizeof state->app_name_buffer,
"app_%d", uid - AID_APP );
pw->pw_name = state->app_name_buffer;
pw->pw_dir = "/data";
pw->pw_shell = "/system/bin/sh";
pw->pw_uid = uid;
pw->pw_gid = uid;
return pw;
return app_id_to_passwd(uid, state);
}
struct passwd* getpwnam(const char *login)
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;
}

793
libc/bionic/time64.c Normal file
View File

@ -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));
}

View File

@ -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

364
libc/docs/OVERVIEW.TXT Normal file
View File

@ -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.

View File

@ -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,

View File

@ -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

View File

@ -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 *);

View File

@ -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; \

View File

@ -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;

54
libc/include/time64.h Normal file
View File

@ -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 */

View File

@ -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 *);

40
libc/string/strcoll.c Executable file
View File

@ -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);
}

47
libc/string/strxfrm.c Executable file
View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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>

View File

@ -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_

View File

@ -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_

View File

@ -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.
*/
/*
* This function is an empty stub where GDB locates a breakpoint to get notified
* about linker activity.