| OLD | NEW |
| 1 // nacl_file.cc -- handle file lookups for NaCl version of gold -*- C++ -*- | 1 // nacl_file.cc -- handle file lookups for NaCl version of gold -*- C++ -*- |
| 2 | 2 |
| 3 // Copyright 2012 Free Software Foundation, Inc. | 3 // Copyright 2012 Free Software Foundation, Inc. |
| 4 // Written by the Native Client authors. | 4 // Written by the Native Client authors. |
| 5 | 5 |
| 6 // This file is part of gold. | 6 // This file is part of gold. |
| 7 | 7 |
| 8 // This program is free software; you can redistribute it and/or modify | 8 // This program is free software; you can redistribute it and/or modify |
| 9 // it under the terms of the GNU General Public License as published by | 9 // it under the terms of the GNU General Public License as published by |
| 10 // the Free Software Foundation; either version 3 of the License, or | 10 // the Free Software Foundation; either version 3 of the License, or |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #if !defined(__native_client__) | 26 #if !defined(__native_client__) |
| 27 #error "Cannot build nacl_file.cc without __native_client__" | 27 #error "Cannot build nacl_file.cc without __native_client__" |
| 28 #endif | 28 #endif |
| 29 | 29 |
| 30 #include <fcntl.h> | 30 #include <fcntl.h> |
| 31 #include <map> | 31 #include <map> |
| 32 #include <string> | 32 #include <string> |
| 33 #include <unistd.h> | 33 #include <unistd.h> |
| 34 #include <vector> | 34 #include <vector> |
| 35 | 35 |
| 36 #include "native_client/src/public/imc_syscalls.h" | 36 #include <irt.h> |
| 37 #include "native_client/src/public/name_service.h" | |
| 38 #include "native_client/src/shared/srpc/nacl_srpc.h" | 37 #include "native_client/src/shared/srpc/nacl_srpc.h" |
| 39 | 38 |
| 40 #include "gold.h" | 39 #include "gold.h" |
| 41 | 40 |
| 42 using namespace gold; | 41 using namespace gold; |
| 43 | 42 |
| 44 extern int gold_main(int argc, char** argv); | 43 extern int gold_main(int argc, char** argv); |
| 45 | 44 |
| 46 #define FILENAME_OUTPUT "a.out" | 45 #define FILENAME_OUTPUT "a.out" |
| 47 #define FILENAME_OBJ "__PNACL_GENERATED" | 46 #define FILENAME_OBJ "__PNACL_GENERATED" |
| 48 | 47 |
| 49 const int kMaxArgc = 256; | 48 const int kMaxArgc = 256; |
| 50 // This value cannot change without also changing the signature of the | 49 // This value cannot change without also changing the signature of the |
| 51 // RunWithSplit RPC | 50 // RunWithSplit RPC |
| 52 const int kMaxObjectFiles = 16; | 51 const int kMaxObjectFiles = 16; |
| 53 | 52 |
| 54 namespace | 53 namespace |
| 55 { | 54 { |
| 56 std::map<std::string, int> g_preopened_files; | 55 std::map<std::string, int> g_preopened_files; |
| 56 struct nacl_irt_resource_open g_irt_resource_open; |
| 57 | 57 |
| 58 // Register some filename -> fd mappings so that we do not | 58 // Register some filename -> fd mappings that correspond to pre-opened fds. |
| 59 // need to use the ManifestNameService (aka directory) service. | 59 // Otherwise files are opened via the IRT open_resource() function. |
| 60 // Note, there seems to be the following convention: | |
| 61 // the directory service knows about files like "files/<filename>". | |
| 62 // Locally, we refer to the files as <filename>. | |
| 63 // For object files passed in via Srpc, we register the incoming .o | |
| 64 // descriptor as FILENAME_OBJ WITHOUT the "files/" prefix. | |
| 65 void RegisterPreopenedFd(const char* filename, int fd) { | 60 void RegisterPreopenedFd(const char* filename, int fd) { |
| 66 std::string key(filename); | 61 std::string key(filename); |
| 67 std::map<std::string, int>::iterator it = g_preopened_files.find(key); | 62 std::map<std::string, int>::iterator it = g_preopened_files.find(key); |
| 68 | 63 |
| 69 if (it != g_preopened_files.end()) { | 64 if (it != g_preopened_files.end()) { |
| 70 gold_fatal(_("nacl_file::set_preopened_fd already set %s to %d."), | 65 gold_fatal(_("nacl_file::set_preopened_fd already set %s to %d."), |
| 71 filename, it->second); | 66 filename, it->second); |
| 72 } else { | 67 } else { |
| 73 g_preopened_files[key] = fd; | 68 g_preopened_files[key] = fd; |
| 74 } | 69 } |
| 75 } | 70 } |
| 76 | 71 |
| 77 // Look up additional resource files through the nacl manifest service | 72 // Set up interfaces for IRT open_resource. |
| 78 // which essentially maps a (file)name to a (file)descriptor | 73 void GetIRTInterface() { |
| 79 NaClSrpcChannel g_nacl_manifest_channel; | 74 size_t query_result = nacl_interface_query( |
| 80 | 75 NACL_IRT_RESOURCE_OPEN_v0_1, |
| 81 // Make ManifestNameService service available for lookups. | 76 &g_irt_resource_open, sizeof(g_irt_resource_open)); |
| 82 void ManifestLookupInit() { | 77 if (query_result != sizeof(g_irt_resource_open)) { |
| 83 int nameservice_address = -1; | 78 gold_fatal(_("nacl_file::GetIRTInterface failed")); |
| 84 int nameservice_fd = -1; | |
| 85 int manifest_address = -1; | |
| 86 int manifest_fd = -1; | |
| 87 int status; | |
| 88 NaClSrpcChannel nameservice_channel; | |
| 89 | |
| 90 /* Attach to the reverse service for doing manifest file queries. */ | |
| 91 nacl_nameservice(&nameservice_address); | |
| 92 if (nameservice_address == -1) { | |
| 93 gold_fatal(_("nacl_nameservice failed\n")); | |
| 94 } | |
| 95 nameservice_fd = imc_connect(nameservice_address); | |
| 96 close(nameservice_address); | |
| 97 if (nameservice_fd == -1) { | |
| 98 gold_fatal(_("name service connect failed\n")); | |
| 99 } | |
| 100 if (!NaClSrpcClientCtor(&nameservice_channel, nameservice_fd)) { | |
| 101 gold_fatal(_("name service channel ctor failed\n")); | |
| 102 } | |
| 103 if (NACL_SRPC_RESULT_OK != | |
| 104 NaClSrpcInvokeBySignature(&nameservice_channel, NACL_NAME_SERVICE_LOOKUP, | |
| 105 "ManifestNameService", O_RDWR, | |
| 106 &status, &manifest_address)) { | |
| 107 gold_fatal(_("ManifestNameService SRPC failed, status %d\n"), status); | |
| 108 } | |
| 109 NaClSrpcDtor(&nameservice_channel); | |
| 110 if (manifest_address == -1) { | |
| 111 gold_fatal(_("manifest name service address is -1\n")); | |
| 112 } | |
| 113 manifest_fd = imc_connect(manifest_address); | |
| 114 close(manifest_address); | |
| 115 if (manifest_fd == -1) { | |
| 116 gold_fatal(_("manifest name service connect failed\n")); | |
| 117 } | |
| 118 if (!NaClSrpcClientCtor(&g_nacl_manifest_channel, manifest_fd)) { | |
| 119 gold_fatal(_("manifest channel ctor failed\n")); | |
| 120 } | 79 } |
| 121 } | 80 } |
| 122 | 81 |
| 123 void ManifestLookupFini() { | 82 int IrtOpenFile(const char* filename) { |
| 124 NaClSrpcDtor(&g_nacl_manifest_channel); | 83 int fd = -1; |
| 125 } | 84 if (int res = g_irt_resource_open.open_resource(filename, &fd)) { |
| 126 | 85 gold_fatal(_("IrtOpenFile (%s) failed: %d\n"), filename, res); |
| 127 const int kUnknownFd = -1; | |
| 128 | |
| 129 int LookupFileByName(const char* filename) { | |
| 130 int fd = kUnknownFd; | |
| 131 int status; | |
| 132 // Files looked up via the nameservice are assumed to have a "files/" prefix. | |
| 133 std::string prefix("files/"); | |
| 134 std::string full_filename = prefix + std::string(filename); | |
| 135 NaClSrpcError error = | |
| 136 NaClSrpcInvokeBySignature(&g_nacl_manifest_channel, | |
| 137 NACL_NAME_SERVICE_LOOKUP, | |
| 138 full_filename.c_str(), | |
| 139 O_RDONLY, | |
| 140 &status, | |
| 141 &fd); | |
| 142 if (error != NACL_SRPC_RESULT_OK) { | |
| 143 gold_fatal(_("Lookup (%s) failed.\n"), filename); | |
| 144 } | 86 } |
| 145 return fd; | 87 return fd; |
| 146 } | 88 } |
| 147 | 89 |
| 148 void RunCommon(const std::vector<std::string>& arg_vec, | 90 void RunCommon(const std::vector<std::string>& arg_vec, |
| 149 NaClSrpcRpc* rpc, | 91 NaClSrpcRpc* rpc, |
| 150 NaClSrpcClosure* done) { | 92 NaClSrpcClosure* done) { |
| 151 // repackage the commandline to what main() expects | 93 // repackage the commandline to what main() expects |
| 152 const char* argv[kMaxArgc]; | 94 const char* argv[kMaxArgc]; |
| 153 if (arg_vec.size() > kMaxArgc) { | 95 if (arg_vec.size() > kMaxArgc) { |
| 154 gold_fatal(_("commandline too long")); | 96 gold_fatal(_("commandline too long")); |
| 155 } | 97 } |
| 156 for (size_t i = 0; i < arg_vec.size(); ++i) argv[i] = arg_vec[i].c_str(); | 98 for (size_t i = 0; i < arg_vec.size(); ++i) argv[i] = arg_vec[i].c_str(); |
| 157 | 99 |
| 158 // call hijacked main() | 100 // call hijacked main() |
| 159 int ret = gold_main(arg_vec.size(), const_cast<char**>(&argv[0])); | 101 int ret = gold_main(arg_vec.size(), const_cast<char**>(&argv[0])); |
| 160 rpc->result = ret > 0 ? NACL_SRPC_RESULT_APP_ERROR : NACL_SRPC_RESULT_OK; | 102 rpc->result = ret > 0 ? NACL_SRPC_RESULT_APP_ERROR : NACL_SRPC_RESULT_OK; |
| 161 done->Run(done); | 103 done->Run(done); |
| 162 } | 104 } |
| 163 | 105 |
| 164 | 106 // c.f.: pnacl/driver/nativeld.py |
| 165 // c.f.: pnacl/driver/pnacl-nativeld.py | |
| 166 const char* kDefaultCommandCommon[] = { | 107 const char* kDefaultCommandCommon[] = { |
| 167 "gold", | 108 "gold", |
| 168 "--eh-frame-hdr", | 109 "--eh-frame-hdr", |
| 169 "-nostdlib", | 110 "-nostdlib", |
| 170 // ARM only but added to everything for convenience | 111 // ARM only but added to everything for convenience |
| 171 "--no-fix-cortex-a8", | 112 "--no-fix-cortex-a8", |
| 172 "-o", | 113 "-o", |
| 173 FILENAME_OUTPUT, | 114 FILENAME_OUTPUT, |
| 174 0 | 115 0 |
| 175 }; | 116 }; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 } | 192 } |
| 252 command_line[arg] = 0; | 193 command_line[arg] = 0; |
| 253 | 194 |
| 254 ProcessCommandline(command_line, &result_arg_vec); | 195 ProcessCommandline(command_line, &result_arg_vec); |
| 255 for (int i = 0; i < object_count; i++) { | 196 for (int i = 0; i < object_count; i++) { |
| 256 delete [] filenames[i]; | 197 delete [] filenames[i]; |
| 257 } | 198 } |
| 258 RunCommon(result_arg_vec, rpc, done); | 199 RunCommon(result_arg_vec, rpc, done); |
| 259 } | 200 } |
| 260 | 201 |
| 261 } // End namespace gold. | 202 } // End anonymous namespace. |
| 262 | 203 |
| 263 namespace nacl_file | 204 namespace nacl_file |
| 264 { | 205 { |
| 265 | 206 |
| 266 // This is the only exported API from this file | |
| 267 int NaClOpenFileDescriptor(const char *filename) { | 207 int NaClOpenFileDescriptor(const char *filename) { |
| 268 std::string key(filename); | 208 std::string key(filename); |
| 269 std::map<std::string, int>::iterator it = g_preopened_files.find(key); | 209 std::map<std::string, int>::iterator it = g_preopened_files.find(key); |
| 270 int fd; | 210 int fd; |
| 211 // First check if it is a pre-opened file. |
| 271 if (it != g_preopened_files.end()) { | 212 if (it != g_preopened_files.end()) { |
| 272 fd = it->second; | 213 fd = it->second; |
| 273 } else { | 214 } else { |
| 274 // Otherwise, ask the nameservice. | 215 // Otherwise, open the file through the IRT. |
| 275 fd = LookupFileByName(filename); | 216 fd = IrtOpenFile(filename); |
| 276 } | 217 } |
| 277 // in case the file was re-opened, say to do --start/end-group | 218 // In case the file was re-opened, seek back to the beginning. |
| 219 // This might be the case for the --start/end-group implementation. |
| 278 lseek(fd, 0, SEEK_SET); | 220 lseek(fd, 0, SEEK_SET); |
| 279 return fd; | 221 return fd; |
| 280 } | 222 } |
| 281 | 223 |
| 282 void NaClReleaseFileDescriptor(int fd) { | 224 void NaClReleaseFileDescriptor(int fd) { |
| 283 // Note: we do not close the fd as it maybe opened again. | 225 // Note: we do not close the fd as it maybe opened again. |
| 284 // For now we are getting lucky: | 226 // For now we are getting lucky: |
| 285 // gold is not closing any of the libraries. And it IS closing | 227 // gold is not closing any of the libraries. And it IS closing |
| 286 // the nexe for us in Output_file::close | 228 // the nexe for us in Output_file::close |
| 287 } | 229 } |
| 288 | 230 |
| 289 } // End namespace nacl_file. | 231 } // End namespace nacl_file. |
| 290 | 232 |
| 291 | 233 |
| 292 int | 234 int main() { |
| 293 main() | |
| 294 { | |
| 295 if (!NaClSrpcModuleInit()) { | 235 if (!NaClSrpcModuleInit()) { |
| 296 gold_fatal(_("NaClSrpcModuleInit failed\n")); | 236 gold_fatal(_("NaClSrpcModuleInit failed\n")); |
| 297 } | 237 } |
| 298 ManifestLookupInit(); | 238 GetIRTInterface(); |
| 299 | 239 |
| 300 // Start the message loop to process SRPCs. | 240 // Start the message loop to process SRPCs. |
| 301 // It usually never terminates unless killed. | 241 // It usually never terminates unless killed. |
| 302 const struct NaClSrpcHandlerDesc srpc_methods[] = { | 242 const struct NaClSrpcHandlerDesc srpc_methods[] = { |
| 303 { "RunWithSplit:ihhhhhhhhhhhhhhhhh:", SrpcRunWithSplit }, | 243 { "RunWithSplit:ihhhhhhhhhhhhhhhhh:", SrpcRunWithSplit }, |
| 304 { NULL, NULL }, | 244 { NULL, NULL }, |
| 305 }; | 245 }; |
| 306 | 246 |
| 307 if (!NaClSrpcAcceptClientConnection(srpc_methods)) { | 247 if (!NaClSrpcAcceptClientConnection(srpc_methods)) { |
| 308 gold_fatal(_("NaClSrpcAcceptClientConnection failed\n")); | 248 gold_fatal(_("NaClSrpcAcceptClientConnection failed\n")); |
| 309 } | 249 } |
| 310 | 250 |
| 311 ManifestLookupFini(); | |
| 312 NaClSrpcModuleFini(); | 251 NaClSrpcModuleFini(); |
| 313 return 0; | 252 return 0; |
| 314 } | 253 } |
| OLD | NEW |