| /* |
| * Copyright 2016 WebAssembly Community Group participants |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "wabt/common.h" |
| |
| #include <cassert> |
| #include <cerrno> |
| #include <climits> |
| #include <cstdint> |
| #include <cstdio> |
| #include <cstring> |
| |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| |
| #if COMPILER_IS_MSVC |
| #include <fcntl.h> |
| #include <io.h> |
| #include <stdlib.h> |
| #define PATH_MAX _MAX_PATH |
| #define stat _stat |
| #define S_IFREG _S_IFREG |
| #endif |
| |
| namespace wabt { |
| |
| Reloc::Reloc(RelocType type, Offset offset, Index index, int32_t addend) |
| : type(type), offset(offset), index(index), addend(addend) {} |
| |
| const char* g_kind_name[] = {"func", "table", "memory", "global", "tag"}; |
| WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(g_kind_name) == kExternalKindCount); |
| |
| const char* g_reloc_type_name[] = { |
| "R_WASM_FUNCTION_INDEX_LEB", "R_WASM_TABLE_INDEX_SLEB", |
| "R_WASM_TABLE_INDEX_I32", "R_WASM_MEMORY_ADDR_LEB", |
| "R_WASM_MEMORY_ADDR_SLEB", "R_WASM_MEMORY_ADDR_I32", |
| "R_WASM_TYPE_INDEX_LEB", "R_WASM_GLOBAL_INDEX_LEB", |
| "R_WASM_FUNCTION_OFFSET_I32", "R_WASM_SECTION_OFFSET_I32", |
| "R_WASM_TAG_INDEX_LEB", "R_WASM_MEMORY_ADDR_REL_SLEB", |
| "R_WASM_TABLE_INDEX_REL_SLEB", "R_WASM_GLOBAL_INDEX_I32", |
| "R_WASM_MEMORY_ADDR_LEB64", "R_WASM_MEMORY_ADDR_SLEB64", |
| "R_WASM_MEMORY_ADDR_I64", "R_WASM_MEMORY_ADDR_REL_SLEB64", |
| "R_WASM_TABLE_INDEX_SLEB64", "R_WASM_TABLE_INDEX_I64", |
| "R_WASM_TABLE_NUMBER_LEB", "R_WASM_MEMORY_ADDR_TLS_SLEB", |
| "R_WASM_MEMORY_ADDR_TLS_I32", |
| }; |
| WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(g_reloc_type_name) == kRelocTypeCount); |
| |
| static Result ReadAll(FILE* stream, |
| const char* name, |
| std::vector<uint8_t>* out_data) { |
| out_data->resize(0); |
| uint8_t buffer[4096]; |
| while (true) { |
| size_t bytes_read = fread(buffer, 1, sizeof(buffer), stream); |
| if (bytes_read == 0) { |
| if (ferror(stream)) { |
| fprintf(stderr, "error reading from %s: %s\n", name, strerror(errno)); |
| return Result::Error; |
| } |
| return Result::Ok; |
| } |
| size_t old_size = out_data->size(); |
| out_data->resize(old_size + bytes_read); |
| memcpy(out_data->data() + old_size, buffer, bytes_read); |
| } |
| } |
| |
| Result ReadFile(std::string_view filename, std::vector<uint8_t>* out_data) { |
| std::string filename_str(filename); |
| const char* filename_cstr = filename_str.c_str(); |
| |
| if (filename == "-") { |
| return ReadAll(stdin, "stdin", out_data); |
| } |
| |
| struct stat statbuf; |
| if (stat(filename_cstr, &statbuf) < 0) { |
| fprintf(stderr, "%s: %s\n", filename_cstr, strerror(errno)); |
| return Result::Error; |
| } |
| |
| if (statbuf.st_mode & S_IFDIR) { |
| fprintf(stderr, "%s: is a directory\n", filename_cstr); |
| return Result::Error; |
| } |
| |
| FILE* infile = fopen(filename_cstr, "rb"); |
| if (!infile) { |
| fprintf(stderr, "%s: %s\n", filename_cstr, strerror(errno)); |
| return Result::Error; |
| } |
| |
| if (fseek(infile, 0, SEEK_END) < 0) { |
| // not seekable, so we can't pre-allocate out_data, but let's try and read |
| // it anyway (for pipes, sockets, etc.) |
| auto res = ReadAll(infile, filename_cstr, out_data); |
| fclose(infile); |
| return res; |
| } |
| |
| long size = ftell(infile); |
| if (size < 0) { |
| perror("ftell failed"); |
| fclose(infile); |
| return Result::Error; |
| } |
| |
| if (fseek(infile, 0, SEEK_SET) < 0) { |
| perror("fseek to beginning failed"); |
| fclose(infile); |
| return Result::Error; |
| } |
| |
| out_data->resize(size); |
| if (size != 0 && fread(out_data->data(), size, 1, infile) != 1) { |
| fprintf(stderr, "%s: fread failed: %s\n", filename_cstr, strerror(errno)); |
| fclose(infile); |
| return Result::Error; |
| } |
| |
| fclose(infile); |
| return Result::Ok; |
| } |
| |
| void InitStdio() { |
| #if COMPILER_IS_MSVC |
| int result = _setmode(_fileno(stdout), _O_BINARY); |
| if (result == -1) { |
| perror("Cannot set mode binary to stdout"); |
| } |
| result = _setmode(_fileno(stderr), _O_BINARY); |
| if (result == -1) { |
| perror("Cannot set mode binary to stderr"); |
| } |
| #endif |
| } |
| |
| } // namespace wabt |