* 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:
parent
1b3b00c2a1
commit
2716cfd3d7
@ -23,11 +23,6 @@ struct stat {
|
||||
time_t st_mtime; /* last modification time */
|
||||
time_t st_ctime; /* last change time, not 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 */
|
||||
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 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 fstat(int fd, 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
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ typedef struct image_t {
|
||||
int major;
|
||||
int middle;
|
||||
int minor;
|
||||
bool haiku;
|
||||
} gcc_version;
|
||||
|
||||
addr_t entry_point;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@ -18,63 +18,71 @@
|
||||
return err;
|
||||
|
||||
|
||||
// R5 compatibility
|
||||
#define R5_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);
|
||||
// BeOS compatibility
|
||||
#define BEOS_STAT_SIZE 60
|
||||
|
||||
|
||||
int
|
||||
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
|
||||
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
|
||||
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
|
||||
_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);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#endif // !_KERNEL_MODE
|
||||
|
@ -651,6 +651,7 @@ analyze_object_gcc_version(int fd, image_t* image, Elf32_Ehdr& eheader,
|
||||
int gccMajor = 0;
|
||||
int gccMiddle = 0;
|
||||
int gccMinor = 0;
|
||||
bool isHaiku = true;
|
||||
|
||||
// Read up to 10 comments. The first three or four are usually from the
|
||||
// glue code.
|
||||
@ -720,11 +721,15 @@ analyze_object_gcc_version(int fd, image_t* image, Elf32_Ehdr& eheader,
|
||||
gccMiddle = version[1];
|
||||
gccMinor = version[2];
|
||||
}
|
||||
|
||||
if (gccMajor == 2 && strcmp(gccPlatform, "haiku"))
|
||||
isHaiku = false;
|
||||
}
|
||||
|
||||
image->gcc_version.major = gccMajor;
|
||||
image->gcc_version.middle = gccMiddle;
|
||||
image->gcc_version.minor = gccMinor;
|
||||
image->gcc_version.haiku = isHaiku;
|
||||
|
||||
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
|
||||
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) {
|
||||
case SHN_UNDEF:
|
||||
{
|
||||
struct Elf32_Sym *sharedSym;
|
||||
image_t *sharedImage;
|
||||
const char *symName;
|
||||
|
||||
// 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
|
||||
sym2 = find_undefined_symbol(rootImage, image, symname, &shimg);
|
||||
if (!sym2) {
|
||||
sharedSym = find_undefined_symbol(rootImage, image, symName,
|
||||
&sharedImage);
|
||||
if (sharedSym == NULL) {
|
||||
FATAL("elf_resolve_symbol: could not resolve symbol '%s'\n",
|
||||
symname);
|
||||
symName);
|
||||
return B_MISSING_SYMBOL;
|
||||
}
|
||||
|
||||
// make sure they're the same type
|
||||
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 "
|
||||
"but wrong type\n", symname);
|
||||
"but wrong type\n", symName);
|
||||
return B_MISSING_SYMBOL;
|
||||
}
|
||||
|
||||
if (ELF32_ST_BIND(sym2->st_info) != STB_GLOBAL
|
||||
&& ELF32_ST_BIND(sym2->st_info) != STB_WEAK) {
|
||||
if (ELF32_ST_BIND(sharedSym->st_info) != STB_GLOBAL
|
||||
&& ELF32_ST_BIND(sharedSym->st_info) != STB_WEAK) {
|
||||
FATAL("elf_resolve_symbol: found symbol '%s' but not "
|
||||
"exported\n", symname);
|
||||
"exported\n", symName);
|
||||
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;
|
||||
}
|
||||
|
||||
case SHN_ABS:
|
||||
*sym_addr = sym->st_value + image->regions[0].delta;
|
||||
*symAddress = sym->st_value + image->regions[0].delta;
|
||||
return B_NO_ERROR;
|
||||
|
||||
case SHN_COMMON:
|
||||
@ -1149,7 +1190,7 @@ resolve_symbol(image_t *rootImage, image_t *image, struct Elf32_Sym *sym,
|
||||
|
||||
default:
|
||||
// standard symbol
|
||||
*sym_addr = sym->st_value + image->regions[0].delta;
|
||||
*symAddress = sym->st_value + image->regions[0].delta;
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user