xref: /haiku/src/system/libroot/os/Architecture.cpp (revision 22e92014f0dd38c0b621a94af3453a9e15b95609)
1 /*
2  * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <architecture_private.h>
8 
9 #include <stdio.h>
10 #include <string.h>
11 #include <sys/stat.h>
12 
13 #include <OS.h>
14 
15 #include <directories.h>
16 #include <find_directory_private.h>
17 #include <runtime_loader.h>
18 
19 
20 static const char* const kArchitecture = B_HAIKU_ABI_NAME;
21 static const char* const kPrimaryArchitecture = __HAIKU_PRIMARY_PACKAGING_ARCH;
22 
23 #ifdef __HAIKU_ARCH_X86
24 	static const char* const kSiblingArchitectures[] = {"x86_gcc2", "x86"};
25 #else
26 	static const char* const kSiblingArchitectures[] = {};
27 #endif
28 
29 static const size_t kSiblingArchitectureCount
30 	= sizeof(kSiblingArchitectures) / sizeof(const char*);
31 
32 
33 static bool
34 has_secondary_architecture(const char* architecture)
35 {
36 	if (strcmp(architecture, kPrimaryArchitecture) == 0)
37 		return false;
38 
39 	char path[B_PATH_NAME_LENGTH];
40 	snprintf(path, sizeof(path), kSystemLibDirectory "/%s/libroot.so",
41 		architecture);
42 
43 	struct stat st;
44 	return lstat(path, &st) == 0;
45 }
46 
47 
48 // #pragma mark -
49 
50 
51 const char*
52 __get_architecture()
53 {
54 	return kArchitecture;
55 }
56 
57 
58 const char*
59 __get_primary_architecture()
60 {
61 	return kPrimaryArchitecture;
62 }
63 
64 
65 size_t
66 __get_secondary_architectures(const char** architectures, size_t count)
67 {
68 	size_t index = 0;
69 
70 	// If this is an architecture that could be a primary or secondary
71 	// architecture, check for which architectures a libroot.so is present.
72 	if (kSiblingArchitectureCount > 0) {
73 		for (size_t i = 0; i < kSiblingArchitectureCount; i++) {
74 			const char* architecture = kSiblingArchitectures[i];
75 			if (!has_secondary_architecture(architecture))
76 				continue;
77 
78 			if (index < count)
79 				architectures[index] = architecture;
80 			index++;
81 		}
82 	}
83 
84 	return index;
85 }
86 
87 
88 size_t
89 __get_architectures(const char** architectures, size_t count)
90 {
91 	if (count == 0)
92 		return __get_secondary_architectures(NULL, 0) + 1;
93 
94 	architectures[0] = __get_primary_architecture();
95 	return __get_secondary_architectures(architectures + 1, count -1) + 1;
96 }
97 
98 
99 const char*
100 __guess_architecture_for_path(const char* path)
101 {
102 	if (kSiblingArchitectureCount == 0)
103 		return kPrimaryArchitecture;
104 
105 	// ask the runtime loader
106 	const char* architecture;
107 	if (__gRuntimeLoader->get_executable_architecture(path, &architecture)
108 			== B_OK) {
109 		// verify that it is one of the sibling architectures
110 		for (size_t i = 0; i < kSiblingArchitectureCount; i++) {
111 			if (strcmp(architecture, kSiblingArchitectures[i]) == 0)
112 				return kSiblingArchitectures[i];
113 		}
114 	}
115 
116 	// guess from the given path
117 	architecture = __guess_secondary_architecture_from_path(path,
118 		kSiblingArchitectures, kSiblingArchitectureCount);
119 
120 	return architecture != NULL && has_secondary_architecture(architecture)
121 		? architecture : kPrimaryArchitecture;
122 }
123 
124 
125 B_DEFINE_WEAK_ALIAS(__get_architecture, get_architecture);
126 B_DEFINE_WEAK_ALIAS(__get_primary_architecture, get_primary_architecture);
127 B_DEFINE_WEAK_ALIAS(__get_secondary_architectures, get_secondary_architectures);
128 B_DEFINE_WEAK_ALIAS(__get_architectures, get_architectures);
129 B_DEFINE_WEAK_ALIAS(__guess_architecture_for_path, guess_architecture_for_path);
130