Chromium Code Reviews| 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 "native_client/src/untrusted/irt/irt.h" |
|
Mark Seaborn
2014/12/01 19:26:43
I believe this can be #included as <irt.h>, which
jvoung (off chromium)
2014/12/01 20:35:19
Done.
| |
| 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; |
| 57 | 56 |
| 58 // Register some filename -> fd mappings so that we do not | 57 // Register some filename -> fd mappings that correspond to pre-opened fds. |
| 59 // need to use the ManifestNameService (aka directory) service. | 58 // 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) { | 59 void RegisterPreopenedFd(const char* filename, int fd) { |
| 66 std::string key(filename); | 60 std::string key(filename); |
| 67 std::map<std::string, int>::iterator it = g_preopened_files.find(key); | 61 std::map<std::string, int>::iterator it = g_preopened_files.find(key); |
| 68 | 62 |
| 69 if (it != g_preopened_files.end()) { | 63 if (it != g_preopened_files.end()) { |
| 70 gold_fatal(_("nacl_file::set_preopened_fd already set %s to %d."), | 64 gold_fatal(_("nacl_file::set_preopened_fd already set %s to %d."), |
| 71 filename, it->second); | 65 filename, it->second); |
| 72 } else { | 66 } else { |
| 73 g_preopened_files[key] = fd; | 67 g_preopened_files[key] = fd; |
| 74 } | 68 } |
| 75 } | 69 } |
| 76 | 70 |
| 77 // Look up additional resource files through the nacl manifest service | 71 static struct nacl_irt_resource_open g_irt_resource_open; |
|
Mark Seaborn
2014/12/01 19:26:43
"static" not neeed -- this is inside an anon names
jvoung (off chromium)
2014/12/01 20:35:19
Done.
| |
| 78 // which essentially maps a (file)name to a (file)descriptor | |
| 79 NaClSrpcChannel g_nacl_manifest_channel; | |
| 80 | 72 |
| 81 // Make ManifestNameService service available for lookups. | 73 // Set up interfaces for IRT open_resource. |
| 82 void ManifestLookupInit() { | 74 void GetIRTInterface() { |
| 83 int nameservice_address = -1; | 75 size_t query_result = nacl_interface_query( |
| 84 int nameservice_fd = -1; | 76 NACL_IRT_RESOURCE_OPEN_v0_1, |
| 85 int manifest_address = -1; | 77 &g_irt_resource_open, sizeof(g_irt_resource_open)); |
| 86 int manifest_fd = -1; | 78 if (query_result != sizeof(g_irt_resource_open)) { |
| 87 int status; | 79 gold_fatal(_("nacl_file::GetIRTInterface failed")); |
| 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 } | 80 } |
| 121 } | 81 } |
| 122 | 82 |
| 123 void ManifestLookupFini() { | 83 int IrtOpenFile(const char* filename) { |
| 124 NaClSrpcDtor(&g_nacl_manifest_channel); | 84 int fd = -1; |
| 125 } | 85 if (int res = g_irt_resource_open.open_resource(filename, &fd)) { |
| 126 | 86 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 } | 87 } |
| 145 return fd; | 88 return fd; |
| 146 } | 89 } |
| 147 | 90 |
| 148 void RunCommon(const std::vector<std::string>& arg_vec, | 91 void RunCommon(const std::vector<std::string>& arg_vec, |
| 149 NaClSrpcRpc* rpc, | 92 NaClSrpcRpc* rpc, |
| 150 NaClSrpcClosure* done) { | 93 NaClSrpcClosure* done) { |
| 151 // repackage the commandline to what main() expects | 94 // repackage the commandline to what main() expects |
| 152 const char* argv[kMaxArgc]; | 95 const char* argv[kMaxArgc]; |
| 153 if (arg_vec.size() > kMaxArgc) { | 96 if (arg_vec.size() > kMaxArgc) { |
| 154 gold_fatal(_("commandline too long")); | 97 gold_fatal(_("commandline too long")); |
| 155 } | 98 } |
| 156 for (size_t i = 0; i < arg_vec.size(); ++i) argv[i] = arg_vec[i].c_str(); | 99 for (size_t i = 0; i < arg_vec.size(); ++i) argv[i] = arg_vec[i].c_str(); |
| 157 | 100 |
| 158 // call hijacked main() | 101 // call hijacked main() |
| 159 int ret = gold_main(arg_vec.size(), const_cast<char**>(&argv[0])); | 102 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; | 103 rpc->result = ret > 0 ? NACL_SRPC_RESULT_APP_ERROR : NACL_SRPC_RESULT_OK; |
| 161 done->Run(done); | 104 done->Run(done); |
| 162 } | 105 } |
| 163 | 106 |
| 164 | 107 // c.f.: pnacl/driver/nativeld.py |
| 165 // c.f.: pnacl/driver/pnacl-nativeld.py | |
| 166 const char* kDefaultCommandCommon[] = { | 108 const char* kDefaultCommandCommon[] = { |
| 167 "gold", | 109 "gold", |
| 168 "--eh-frame-hdr", | 110 "--eh-frame-hdr", |
| 169 "-nostdlib", | 111 "-nostdlib", |
| 170 // ARM only but added to everything for convenience | 112 // ARM only but added to everything for convenience |
| 171 "--no-fix-cortex-a8", | 113 "--no-fix-cortex-a8", |
| 172 "-o", | 114 "-o", |
| 173 FILENAME_OUTPUT, | 115 FILENAME_OUTPUT, |
| 174 0 | 116 0 |
| 175 }; | 117 }; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 251 } | 193 } |
| 252 command_line[arg] = 0; | 194 command_line[arg] = 0; |
| 253 | 195 |
| 254 ProcessCommandline(command_line, &result_arg_vec); | 196 ProcessCommandline(command_line, &result_arg_vec); |
| 255 for (int i = 0; i < object_count; i++) { | 197 for (int i = 0; i < object_count; i++) { |
| 256 delete [] filenames[i]; | 198 delete [] filenames[i]; |
| 257 } | 199 } |
| 258 RunCommon(result_arg_vec, rpc, done); | 200 RunCommon(result_arg_vec, rpc, done); |
| 259 } | 201 } |
| 260 | 202 |
| 261 } // End namespace gold. | 203 } // End anonymous namespace. |
| 262 | 204 |
| 263 namespace nacl_file | 205 namespace nacl_file |
| 264 { | 206 { |
| 265 | 207 |
| 266 // This is the only exported API from this file | |
| 267 int NaClOpenFileDescriptor(const char *filename) { | 208 int NaClOpenFileDescriptor(const char *filename) { |
| 268 std::string key(filename); | 209 std::string key(filename); |
| 269 std::map<std::string, int>::iterator it = g_preopened_files.find(key); | 210 std::map<std::string, int>::iterator it = g_preopened_files.find(key); |
| 270 int fd; | 211 int fd; |
| 212 // First check if it is a pre-opened file. | |
| 271 if (it != g_preopened_files.end()) { | 213 if (it != g_preopened_files.end()) { |
| 272 fd = it->second; | 214 fd = it->second; |
| 273 } else { | 215 } else { |
| 274 // Otherwise, ask the nameservice. | 216 // Otherwise, open the file through the IRT. |
| 275 fd = LookupFileByName(filename); | 217 fd = IrtOpenFile(filename); |
| 276 } | 218 } |
| 277 // in case the file was re-opened, say to do --start/end-group | 219 // In case the file was re-opened, seek back to the beginning. |
| 220 // This might be the case for the --start/end-group implementation. | |
| 278 lseek(fd, 0, SEEK_SET); | 221 lseek(fd, 0, SEEK_SET); |
| 279 return fd; | 222 return fd; |
| 280 } | 223 } |
| 281 | 224 |
| 282 void NaClReleaseFileDescriptor(int fd) { | 225 void NaClReleaseFileDescriptor(int fd) { |
| 283 // Note: we do not close the fd as it maybe opened again. | 226 // Note: we do not close the fd as it maybe opened again. |
| 284 // For now we are getting lucky: | 227 // For now we are getting lucky: |
| 285 // gold is not closing any of the libraries. And it IS closing | 228 // gold is not closing any of the libraries. And it IS closing |
| 286 // the nexe for us in Output_file::close | 229 // the nexe for us in Output_file::close |
| 287 } | 230 } |
| 288 | 231 |
| 289 } // End namespace nacl_file. | 232 } // End namespace nacl_file. |
| 290 | 233 |
| 291 | 234 |
| 292 int | 235 int main() { |
| 293 main() | |
| 294 { | |
| 295 if (!NaClSrpcModuleInit()) { | 236 if (!NaClSrpcModuleInit()) { |
| 296 gold_fatal(_("NaClSrpcModuleInit failed\n")); | 237 gold_fatal(_("NaClSrpcModuleInit failed\n")); |
| 297 } | 238 } |
| 298 ManifestLookupInit(); | 239 GetIRTInterface(); |
| 299 | 240 |
| 300 // Start the message loop to process SRPCs. | 241 // Start the message loop to process SRPCs. |
| 301 // It usually never terminates unless killed. | 242 // It usually never terminates unless killed. |
| 302 const struct NaClSrpcHandlerDesc srpc_methods[] = { | 243 const struct NaClSrpcHandlerDesc srpc_methods[] = { |
| 303 { "RunWithSplit:ihhhhhhhhhhhhhhhhh:", SrpcRunWithSplit }, | 244 { "RunWithSplit:ihhhhhhhhhhhhhhhhh:", SrpcRunWithSplit }, |
| 304 { NULL, NULL }, | 245 { NULL, NULL }, |
| 305 }; | 246 }; |
| 306 | 247 |
| 307 if (!NaClSrpcAcceptClientConnection(srpc_methods)) { | 248 if (!NaClSrpcAcceptClientConnection(srpc_methods)) { |
| 308 gold_fatal(_("NaClSrpcAcceptClientConnection failed\n")); | 249 gold_fatal(_("NaClSrpcAcceptClientConnection failed\n")); |
| 309 } | 250 } |
| 310 | 251 |
| 311 ManifestLookupFini(); | |
| 312 NaClSrpcModuleFini(); | 252 NaClSrpcModuleFini(); |
| 313 return 0; | 253 return 0; |
| 314 } | 254 } |
| OLD | NEW |