* Threw away the broken stat() vs. _stat() mechanism to allow for more fields
in struct stat. * Instead, I followed Marcus' great idea and added a compatibility check in the runtime loader: now, R5 binaries (also shared libraries) are detected, and they get special versions for stat(), fstat(), and lstat() that return the smaller stat struct. * However, I've disabled (in src/system/libroot/posix/sys/stat.c) using the larger stat field for now, as this breaks some of our optional packages. So until we rebuild them all, this shouldn't be enabled. * This should now also be used for BeOS compatibility in libnetwork.so. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27961 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -23,11 +23,6 @@ struct stat {
|
|||||||
time_t st_mtime; /* last modification time */
|
time_t st_mtime; /* last modification time */
|
||||||
time_t st_ctime; /* last change time, not creation time */
|
time_t st_ctime; /* last change time, not creation time */
|
||||||
time_t st_crtime; /* creation time */
|
time_t st_crtime; /* creation time */
|
||||||
|
|
||||||
/* Haiku extensions:
|
|
||||||
* TODO: we might also define special types for files and TTYs
|
|
||||||
* TODO: we should find another solution for this, as BStatable::GetStat()
|
|
||||||
* can only retrieve the R5 stat structure */
|
|
||||||
unsigned int st_type; /* attribute/index type */
|
unsigned int st_type; /* attribute/index type */
|
||||||
blkcnt_t st_blocks; /* number of blocks allocated for object */
|
blkcnt_t st_blocks; /* number of blocks allocated for object */
|
||||||
};
|
};
|
||||||
@@ -104,24 +99,12 @@ extern "C" {
|
|||||||
|
|
||||||
extern int chmod(const char *path, mode_t mode);
|
extern int chmod(const char *path, mode_t mode);
|
||||||
extern int fchmod(int fd, mode_t mode);
|
extern int fchmod(int fd, mode_t mode);
|
||||||
extern int _stat(const char *path, struct stat *st, size_t statSize);
|
|
||||||
extern int _fstat(int fd, struct stat *st, size_t statSize);
|
|
||||||
extern int _lstat(const char *path, struct stat *st, size_t statSize);
|
|
||||||
extern int mkdir(const char *path, mode_t mode);
|
|
||||||
extern int mkfifo(const char *path, mode_t mode);
|
|
||||||
extern mode_t umask(mode_t cmask);
|
|
||||||
|
|
||||||
/* This achieves backwards compatibility with R5 */
|
|
||||||
#if 0 /* def HAIKU_TARGET_PLATFORM_HAIKU */
|
|
||||||
#define stat(fd, st) _stat(fd, st, sizeof(struct stat))
|
|
||||||
#define fstat(fd, st) _fstat(fd, st, sizeof(struct stat))
|
|
||||||
#define lstat(fd, st) _lstat(fd, st, sizeof(struct stat))
|
|
||||||
#else
|
|
||||||
/* ... and this fixes the build for R5 for now */
|
|
||||||
extern int stat(const char *path, struct stat *st);
|
extern int stat(const char *path, struct stat *st);
|
||||||
extern int fstat(int fd, struct stat *st);
|
extern int fstat(int fd, struct stat *st);
|
||||||
extern int lstat(const char *path, struct stat *st);
|
extern int lstat(const char *path, struct stat *st);
|
||||||
#endif
|
extern int mkdir(const char *path, mode_t mode);
|
||||||
|
extern int mkfifo(const char *path, mode_t mode);
|
||||||
|
extern mode_t umask(mode_t cmask);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ typedef struct image_t {
|
|||||||
int major;
|
int major;
|
||||||
int middle;
|
int middle;
|
||||||
int minor;
|
int minor;
|
||||||
|
bool haiku;
|
||||||
} gcc_version;
|
} gcc_version;
|
||||||
|
|
||||||
addr_t entry_point;
|
addr_t entry_point;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2006, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2002-2008, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -18,63 +18,71 @@
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
|
||||||
// R5 compatibility
|
// BeOS compatibility
|
||||||
#define R5_STAT_SIZE 60
|
#define BEOS_STAT_SIZE 60
|
||||||
#undef stat
|
|
||||||
#undef fstat
|
|
||||||
#undef lstat
|
|
||||||
|
|
||||||
extern int stat(const char *path, struct stat *stat);
|
|
||||||
extern int fstat(int fd, struct stat *stat);
|
|
||||||
extern int lstat(const char *path, struct stat *stat);
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
stat(const char *path, struct stat *stat)
|
stat(const char *path, struct stat *stat)
|
||||||
{
|
{
|
||||||
return _stat(path, stat, R5_STAT_SIZE);
|
int status = _kern_read_stat(-1, path, true, stat, BEOS_STAT_SIZE/*sizeof(struct stat)*/);
|
||||||
|
|
||||||
|
RETURN_AND_SET_ERRNO(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
fstat(int fd, struct stat *stat)
|
fstat(int fd, struct stat *stat)
|
||||||
{
|
{
|
||||||
return _fstat(fd, stat, R5_STAT_SIZE);
|
int status = _kern_read_stat(fd, NULL, false, stat, BEOS_STAT_SIZE/*sizeof(struct stat)*/);
|
||||||
|
|
||||||
|
RETURN_AND_SET_ERRNO(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
lstat(const char *path, struct stat *stat)
|
lstat(const char *path, struct stat *stat)
|
||||||
{
|
{
|
||||||
return _lstat(path, stat, R5_STAT_SIZE);
|
int status = _kern_read_stat(-1, path, false, stat, BEOS_STAT_SIZE/*sizeof(struct stat)*/);
|
||||||
|
|
||||||
|
RETURN_AND_SET_ERRNO(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark - BeOS compatibility
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _KERNEL_MODE
|
||||||
|
|
||||||
|
int __be_stat(const char *path, struct stat *stat);
|
||||||
|
int __be_fstat(int fd, struct stat *stat);
|
||||||
|
int __be_lstat(const char *path, struct stat *stat);
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_stat(const char *path, struct stat *stat, size_t statSize)
|
__be_stat(const char *path, struct stat *stat)
|
||||||
{
|
{
|
||||||
int status = _kern_read_stat(-1, path, true, stat, statSize);
|
int status = _kern_read_stat(-1, path, true, stat, BEOS_STAT_SIZE);
|
||||||
|
|
||||||
RETURN_AND_SET_ERRNO(status);
|
RETURN_AND_SET_ERRNO(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_lstat(const char *path, struct stat *stat, size_t statSize)
|
__be_fstat(int fd, struct stat *stat)
|
||||||
{
|
{
|
||||||
int status = _kern_read_stat(-1, path, false, stat, statSize);
|
int status = _kern_read_stat(fd, NULL, false, stat, BEOS_STAT_SIZE);
|
||||||
|
|
||||||
RETURN_AND_SET_ERRNO(status);
|
RETURN_AND_SET_ERRNO(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_fstat(int fd, struct stat *stat, size_t statSize)
|
__be_lstat(const char *path, struct stat *stat)
|
||||||
{
|
{
|
||||||
int status = _kern_read_stat(fd, NULL, false, stat, statSize);
|
int status = _kern_read_stat(-1, path, false, stat, BEOS_STAT_SIZE);
|
||||||
|
|
||||||
RETURN_AND_SET_ERRNO(status);
|
RETURN_AND_SET_ERRNO(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // !_KERNEL_MODE
|
||||||
|
|||||||
@@ -651,6 +651,7 @@ analyze_object_gcc_version(int fd, image_t* image, Elf32_Ehdr& eheader,
|
|||||||
int gccMajor = 0;
|
int gccMajor = 0;
|
||||||
int gccMiddle = 0;
|
int gccMiddle = 0;
|
||||||
int gccMinor = 0;
|
int gccMinor = 0;
|
||||||
|
bool isHaiku = true;
|
||||||
|
|
||||||
// Read up to 10 comments. The first three or four are usually from the
|
// Read up to 10 comments. The first three or four are usually from the
|
||||||
// glue code.
|
// glue code.
|
||||||
@@ -720,11 +721,15 @@ analyze_object_gcc_version(int fd, image_t* image, Elf32_Ehdr& eheader,
|
|||||||
gccMiddle = version[1];
|
gccMiddle = version[1];
|
||||||
gccMinor = version[2];
|
gccMinor = version[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gccMajor == 2 && strcmp(gccPlatform, "haiku"))
|
||||||
|
isHaiku = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
image->gcc_version.major = gccMajor;
|
image->gcc_version.major = gccMajor;
|
||||||
image->gcc_version.middle = gccMiddle;
|
image->gcc_version.middle = gccMiddle;
|
||||||
image->gcc_version.minor = gccMinor;
|
image->gcc_version.minor = gccMinor;
|
||||||
|
image->gcc_version.haiku = isHaiku;
|
||||||
|
|
||||||
return gccMajor != 0;
|
return gccMajor != 0;
|
||||||
}
|
}
|
||||||
@@ -1099,47 +1104,83 @@ find_undefined_symbol(image_t* rootImage, image_t* image, const char* name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! This functions is called when we run BeOS images on Haiku.
|
||||||
|
It allows us to redirect functions to ensure compatibility.
|
||||||
|
*/
|
||||||
|
static const char*
|
||||||
|
beos_compatibility_map_symbol(const char* symbolName)
|
||||||
|
{
|
||||||
|
struct symbol_mapping {
|
||||||
|
const char* from;
|
||||||
|
const char* to;
|
||||||
|
};
|
||||||
|
static const struct symbol_mapping kMappings[] = {
|
||||||
|
// TODO: improve this, and also use it for libnet.so compatibility!
|
||||||
|
{"fstat", "__be_fstat"},
|
||||||
|
{"lstat", "__be_lstat"},
|
||||||
|
{"stat", "__be_stat"},
|
||||||
|
};
|
||||||
|
const uint32 kMappingCount = sizeof(kMappings) / sizeof(kMappings[0]);
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < kMappingCount; i++) {
|
||||||
|
if (!strcmp(symbolName, kMappings[i].from))
|
||||||
|
return kMappings[i].to;
|
||||||
|
}
|
||||||
|
|
||||||
|
return symbolName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
resolve_symbol(image_t *rootImage, image_t *image, struct Elf32_Sym *sym,
|
resolve_symbol(image_t *rootImage, image_t *image, struct Elf32_Sym *sym,
|
||||||
addr_t *sym_addr)
|
addr_t *symAddress)
|
||||||
{
|
{
|
||||||
struct Elf32_Sym *sym2;
|
|
||||||
char *symname;
|
|
||||||
image_t *shimg;
|
|
||||||
|
|
||||||
switch (sym->st_shndx) {
|
switch (sym->st_shndx) {
|
||||||
case SHN_UNDEF:
|
case SHN_UNDEF:
|
||||||
|
{
|
||||||
|
struct Elf32_Sym *sharedSym;
|
||||||
|
image_t *sharedImage;
|
||||||
|
const char *symName;
|
||||||
|
|
||||||
// patch the symbol name
|
// patch the symbol name
|
||||||
symname = SYMNAME(image, sym);
|
symName = SYMNAME(image, sym);
|
||||||
|
if (!image->gcc_version.haiku) {
|
||||||
|
// The image has been compiled with a BeOS compiler. This means
|
||||||
|
// we'll have to redirect some functions for compatibility.
|
||||||
|
symName = beos_compatibility_map_symbol(symName);
|
||||||
|
}
|
||||||
|
|
||||||
// it's undefined, must be outside this image, try the other images
|
// it's undefined, must be outside this image, try the other images
|
||||||
sym2 = find_undefined_symbol(rootImage, image, symname, &shimg);
|
sharedSym = find_undefined_symbol(rootImage, image, symName,
|
||||||
if (!sym2) {
|
&sharedImage);
|
||||||
|
if (sharedSym == NULL) {
|
||||||
FATAL("elf_resolve_symbol: could not resolve symbol '%s'\n",
|
FATAL("elf_resolve_symbol: could not resolve symbol '%s'\n",
|
||||||
symname);
|
symName);
|
||||||
return B_MISSING_SYMBOL;
|
return B_MISSING_SYMBOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure they're the same type
|
// make sure they're the same type
|
||||||
if (ELF32_ST_TYPE(sym->st_info) != STT_NOTYPE
|
if (ELF32_ST_TYPE(sym->st_info) != STT_NOTYPE
|
||||||
&& ELF32_ST_TYPE(sym->st_info) != ELF32_ST_TYPE(sym2->st_info)) {
|
&& ELF32_ST_TYPE(sym->st_info)
|
||||||
|
!= ELF32_ST_TYPE(sharedSym->st_info)) {
|
||||||
FATAL("elf_resolve_symbol: found symbol '%s' in shared image "
|
FATAL("elf_resolve_symbol: found symbol '%s' in shared image "
|
||||||
"but wrong type\n", symname);
|
"but wrong type\n", symName);
|
||||||
return B_MISSING_SYMBOL;
|
return B_MISSING_SYMBOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ELF32_ST_BIND(sym2->st_info) != STB_GLOBAL
|
if (ELF32_ST_BIND(sharedSym->st_info) != STB_GLOBAL
|
||||||
&& ELF32_ST_BIND(sym2->st_info) != STB_WEAK) {
|
&& ELF32_ST_BIND(sharedSym->st_info) != STB_WEAK) {
|
||||||
FATAL("elf_resolve_symbol: found symbol '%s' but not "
|
FATAL("elf_resolve_symbol: found symbol '%s' but not "
|
||||||
"exported\n", symname);
|
"exported\n", symName);
|
||||||
return B_MISSING_SYMBOL;
|
return B_MISSING_SYMBOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*sym_addr = sym2->st_value + shimg->regions[0].delta;
|
*symAddress = sharedSym->st_value + sharedImage->regions[0].delta;
|
||||||
return B_NO_ERROR;
|
return B_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
case SHN_ABS:
|
case SHN_ABS:
|
||||||
*sym_addr = sym->st_value + image->regions[0].delta;
|
*symAddress = sym->st_value + image->regions[0].delta;
|
||||||
return B_NO_ERROR;
|
return B_NO_ERROR;
|
||||||
|
|
||||||
case SHN_COMMON:
|
case SHN_COMMON:
|
||||||
@@ -1149,7 +1190,7 @@ resolve_symbol(image_t *rootImage, image_t *image, struct Elf32_Sym *sym,
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
// standard symbol
|
// standard symbol
|
||||||
*sym_addr = sym->st_value + image->regions[0].delta;
|
*symAddress = sym->st_value + image->regions[0].delta;
|
||||||
return B_NO_ERROR;
|
return B_NO_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user