diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 5c5ebdd25..29d4e72e6 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,14 +1,23 @@ -# Contributor Covenant Code of Conduct ++++ +version = "1.4" +aliases = ["/version/1/4"] ++++ -*Note*: this Code of Conduct pertains to individuals' behavior. Please also see the [Organizational Code of Conduct][OCoC]. +# Contributor Covenant Code of Conduct ## Our Pledge -In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to make participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. ## Our Standards -Examples of behavior that contributes to creating a positive environment include: +Examples of behavior that contributes to creating a positive environment +include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences @@ -18,32 +27,55 @@ Examples of behavior that contributes to creating a positive environment include Examples of unacceptable behavior by participants include: -* The use of sexualized language or imagery and unwelcome sexual attention or advances +* The use of sexualized language or imagery and unwelcome sexual attention or + advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment -* Publishing others' private information, such as a physical or electronic address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a professional setting +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting ## Our Responsibilities -Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. ## Scope -This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. +This Code of Conduct applies within all project spaces, and it also applies when +an individual is representing the project or its community in public spaces. +Examples of representing a project or community include using an official +project e-mail address, posting via an official social media account, or acting +as an appointed representative at an online or offline event. Representation of +a project may be further defined and clarified by project maintainers. ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the Bytecode Alliance CoC team at [report@bytecodealliance.org](mailto:report@bytecodealliance.org). The CoC team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The CoC team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at otc.community.care@intel.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. -Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the Bytecode Alliance's leadership. +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html -[OCoC]: ORG_CODE_OF_CONDUCT.md [homepage]: https://www.contributor-covenant.org -[version]: https://www.contributor-covenant.org/version/1/4/ + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9210b3deb..fb4d5d76e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,4 +36,5 @@ We use GitHub issues to track public bugs. Report a bug by [open a new issue](ht Code of Conduct =============== -WAMR is a [Bytecode Alliance](https://bytecodealliance.org/) project, and follows the Bytecode Alliance's [Code of Conduct](CODE_OF_CONDUCT.md) and [Organizational Code of Conduct](ORG_CODE_OF_CONDUCT.md). +This project is governed by the [Contributor Covenant](CODE_OF_CONDUCT.md). +All contributors and participants agree to abide by its terms. diff --git a/ORG_CODE_OF_CONDUCT.md b/ORG_CODE_OF_CONDUCT.md deleted file mode 100644 index e05e40c3c..000000000 --- a/ORG_CODE_OF_CONDUCT.md +++ /dev/null @@ -1,139 +0,0 @@ -# Bytecode Alliance Organizational Code of Conduct (OCoC) - -*Note*: this Code of Conduct pertains to organizations' behavior. Please also see the [Individual Code of Conduct](CODE_OF_CONDUCT.md). - -## Preamble - -The Bytecode Alliance (BA) welcomes involvement from organizations, -including commercial organizations. This document is an -*organizational* code of conduct, intended particularly to provide -guidance to commercial organizations. It is distinct from the -[Individual Code of Conduct (ICoC)](CODE_OF_CONDUCT.md), and does not -replace the ICoC. This OCoC applies to any group of people acting in -concert as a BA member or as a participant in BA activities, whether -or not that group is formally incorporated in some jurisdiction. - -The code of conduct described below is not a set of rigid rules, and -we did not write it to encompass every conceivable scenario that might -arise. For example, it is theoretically possible there would be times -when asserting patents is in the best interest of the BA community as -a whole. In such instances, consult with the BA, strive for -consensus, and interpret these rules with an intent that is generous -to the community the BA serves. - -While we may revise these guidelines from time to time based on -real-world experience, overall they are based on a simple principle: - -*Bytecode Alliance members should observe the distinction between - public community functions and private functions — especially - commercial ones — and should ensure that the latter support, or at - least do not harm, the former.* - -## Guidelines - - * **Do not cause confusion about Wasm standards or interoperability.** - - Having an interoperable WebAssembly core is a high priority for - the BA, and members should strive to preserve that core. It is fine - to develop additional non-standard features or APIs, but they - should always be clearly distinguished from the core interoperable - Wasm. - - Treat the WebAssembly name and any BA-associated names with - respect, and follow BA trademark and branding guidelines. If you - distribute a customized version of software originally produced by - the BA, or if you build a product or service using BA-derived - software, use names that clearly distinguish your work from the - original. (You should still provide proper attribution to the - original, of course, wherever such attribution would normally be - given.) - - Further, do not use the WebAssembly name or BA-associated names in - other public namespaces in ways that could cause confusion, e.g., - in company names, names of commercial service offerings, domain - names, publicly-visible social media accounts or online service - accounts, etc. It may sometimes be reasonable, however, to - register such a name in a new namespace and then immediately donate - control of that account to the BA, because that would help the project - maintain its identity. - - * **Do not restrict contributors.** If your company requires - employees or contractors to sign non-compete agreements, those - agreements must not prevent people from participating in the BA or - contributing to related projects. - - This does not mean that all non-compete agreements are incompatible - with this code of conduct. For example, a company may restrict an - employee's ability to solicit the company's customers. However, an - agreement must not block any form of technical or social - participation in BA activities, including but not limited to the - implementation of particular features. - - The accumulation of experience and expertise in individual persons, - who are ultimately free to direct their energy and attention as - they decide, is one of the most important drivers of progress in - open source projects. A company that limits this freedom may hinder - the success of the BA's efforts. - - * **Do not use patents as offensive weapons.** If any BA participant - prevents the adoption or development of BA technologies by - asserting its patents, that undermines the purpose of the - coalition. The collaboration fostered by the BA cannot include - members who act to undermine its work. - - * **Practice responsible disclosure** for security vulnerabilities. - Use designated, non-public reporting channels to disclose technical - vulnerabilities, and give the project a reasonable period to - respond, remediate, and patch. - - Vulnerability reporters may patch their company's own offerings, as - long as that patching does not significantly delay the reporting of - the vulnerability. Vulnerability information should never be used - for unilateral commercial advantage. Vendors may legitimately - compete on the speed and reliability with which they deploy - security fixes, but withholding vulnerability information damages - everyone in the long run by risking harm to the BA project's - reputation and to the security of all users. - - * **Respect the letter and spirit of open source practice.** While - there is not space to list here all possible aspects of standard - open source practice, some examples will help show what we mean: - - * Abide by all applicable open source license terms. Do not engage - in copyright violation or misattribution of any kind. - - * Do not claim others' ideas or designs as your own. - - * When others engage in publicly visible work (e.g., an upcoming - demo that is coordinated in a public issue tracker), do not - unilaterally announce early releases or early demonstrations of - that work ahead of their schedule in order to secure private - advantage (such as marketplace advantage) for yourself. - - The BA reserves the right to determine what constitutes good open - source practices and to take action as it deems appropriate to - encourage, and if necessary enforce, such practices. - -## Enforcement - -Instances of organizational behavior in violation of the OCoC may -be reported by contacting the Bytecode Alliance CoC team at -[report@bytecodealliance.org](mailto:report@bytecodealliance.org). The -CoC team will review and investigate all complaints, and will respond -in a way that it deems appropriate to the circumstances. The CoC team -is obligated to maintain confidentiality with regard to the reporter of -an incident. Further details of specific enforcement policies may be -posted separately. - -When the BA deems an organization in violation of this OCoC, the BA -will, at its sole discretion, determine what action to take. The BA -will decide what type, degree, and duration of corrective action is -needed, if any, before a violating organization can be considered for -membership (if it was not already a member) or can have its membership -reinstated (if it was a member and the BA canceled its membership due -to the violation). - -In practice, the BA's first approach will be to start a conversation, -with punitive enforcement used only as a last resort. Violations -often turn out to be unintentional and swiftly correctable with all -parties acting in good faith. diff --git a/README.md b/README.md index b19b5033e..bb076f963 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,5 @@ WebAssembly Micro Runtime ========================= - -**A [Bytecode Alliance][BA] project** - -[BA]: https://bytecodealliance.org/ - WebAssembly Micro Runtime (WAMR) is a standalone WebAssembly (WASM) runtime with small footprint. It includes a few parts as below: - A WebAssembly VM core (namely iwasm) - The supporting API's for the WASM applications @@ -14,8 +9,8 @@ WebAssembly Micro Runtime (WAMR) is a standalone WebAssembly (WASM) runtime with Current Features of WAMR ========================= - WASM interpreter (AOT is planned) -- Supports for a subset of Libc. -- Supports "SIDE_MODULE=1" EMCC compilation option +- Supports for a subset of Libc API. +- Supports for [WASI API](https://github.com/WebAssembly/WASI) - Provides embedding C API - Provides a mechanism for exporting native API's to WASM applications - Supports the programming of firmware apps in a large range of languages (C/C++/Java/Rust/Go/TypeScript etc.) @@ -62,7 +57,7 @@ Embed WAMR WAMR can be built into a standalone executable which takes the WASM application file name as input, and then executes it. In some other situations, the WAMR source code is embedded the product code and built into the final product. -WAMR provides a set of C API for loading the WASM module, instantiating the module and invoking a WASM function from a native call. +WAMR provides a set of C API for loading the WASM module, instantiating the module and invoking a WASM function from a native call. See the [doc/embed_wamr.md](./doc/embed_wamr.md) for the details. @@ -71,7 +66,7 @@ WAMR application programming library WAMR defined event driven programming model: - Single thread per WASM app instance -- App must implement system callbacks: on_init, on_destroy +- App must implement system callbacks: on_init, on_destrory In general there are a few API classes for the WASM application programming: @@ -117,7 +112,7 @@ See the [major features releasing history and contributor names](./doc/release_a Roadmap ======= -See the [roadmap](./doc/roadmap.md) to understand what major features are planned or under development. +See the [roadmap](./doc/roadmap.md) to understand what major features are planed or under development. Please submit issues for any new feature request, or your plan for contributing new features. diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 3513b9cb3..000000000 --- a/SECURITY.md +++ /dev/null @@ -1,29 +0,0 @@ -# Security Policy - -Building secure foundations for software development is at the core of what we do in the Bytecode Alliance. Contributions of external security researchers are a vital part of that. - -## Scope - -If you believe you've found a security issue in any website, service, or software owned or operated by the Bytecode Alliance, we encourage you to notify us. - -## How to Submit a Report - -To submit a vulnerability report to the Bytecode Alliance, please contact us at [security@bytecodealliance.org](mailto:security@bytecodealliance.org). Your submission will be reviewed and validated by a member of our security team. - -## Safe Harbor - -The Bytecode Alliance supports safe harbor for security researchers who: - -* Make a good faith effort to avoid privacy violations, destruction of data, and interruption or degradation of our services. -* Only interact with accounts you own or with explicit permission of the account holder. If you do encounter Personally Identifiable Information (PII) contact us immediately, do not proceed with access, and immediately purge any local information. -* Provide us with a reasonable amount of time to resolve vulnerabilities prior to any disclosure to the public or a third-party. - -We will consider activities conducted consistent with this policy to constitute "authorized" conduct and will not pursue civil action or initiate a complaint to law enforcement. We will help to the extent we can if legal action is initiated by a third party against you. - -Please submit a report to us before engaging in conduct that may be inconsistent with or unaddressed by this policy. - -## Preferences - -* Please provide detailed reports with reproducible steps and a clearly defined impact. -* Submit one vulnerability per report. -* Social engineering (e.g. phishing, vishing, smishing) is prohibited. diff --git a/core/app-mgr/app-manager/app_manager.h b/core/app-mgr/app-manager/app_manager.h index 605ec7418..962193d3d 100644 --- a/core/app-mgr/app-manager/app_manager.h +++ b/core/app-mgr/app-manager/app_manager.h @@ -24,10 +24,6 @@ extern "C" { #define app_manager_printf printk #endif -#define ID_HOST -3 -#define ID_APP_MGR -2 -#define ID_NONE (uint32)-1 - #define SEND_ERR_RESPONSE(mid, err_msg) do { \ app_manager_printf("%s\n", err_msg); \ send_error_response_to_host(mid, INTERNAL_SERVER_ERROR_5_00, err_msg); \ diff --git a/core/app-mgr/app-manager/module_utils.c b/core/app-mgr/app-manager/module_utils.c index 44e486edd..7e4505ca2 100644 --- a/core/app-mgr/app-manager/module_utils.c +++ b/core/app-mgr/app-manager/module_utils.c @@ -121,8 +121,9 @@ module_data_list_lookup_id(unsigned int module_id) module_data * app_manager_get_module_data(uint32 module_type, void *module_inst) { - if (g_module_interfaces[module_type] - && g_module_interfaces[module_type]->module_get_module_data) + if (module_type < Module_Max + && g_module_interfaces[module_type] + && g_module_interfaces[module_type]->module_get_module_data) return g_module_interfaces[module_type]->module_get_module_data(module_inst); return NULL; } @@ -130,24 +131,28 @@ app_manager_get_module_data(uint32 module_type, void *module_inst) void* app_manager_get_module_queue(uint32 module_type, void *module_inst) { - return app_manager_get_module_data(module_type, module_inst)->queue; + module_data *m_data = app_manager_get_module_data(module_type, module_inst); + return m_data ? m_data->queue : NULL; } const char* app_manager_get_module_name(uint32 module_type, void *module_inst) { - return app_manager_get_module_data(module_type, module_inst)->module_name; + module_data *m_data = app_manager_get_module_data(module_type, module_inst); + return m_data ? m_data->module_name : NULL; } unsigned int app_manager_get_module_id(uint32 module_type, void *module_inst) { - return app_manager_get_module_data(module_type, module_inst)->id; + module_data *m_data = app_manager_get_module_data(module_type, module_inst); + return m_data ? m_data->id : ID_NONE; } void* app_manager_get_module_heap(uint32 module_type, void *module_inst) { - return app_manager_get_module_data(module_type, module_inst)->heap; + module_data *m_data = app_manager_get_module_data(module_type, module_inst); + return m_data ? m_data->heap : NULL; } module_data* @@ -170,7 +175,8 @@ void app_manager_del_module_data(module_data *m_data) bool app_manager_is_interrupting_module(uint32 module_type, void *module_inst) { - return app_manager_get_module_data(module_type, module_inst)->wd_timer.is_interrupting; + module_data *m_data = app_manager_get_module_data(module_type, module_inst); + return m_data ? m_data->wd_timer.is_interrupting : false; } extern void destroy_module_timer_ctx(unsigned int module_id); diff --git a/core/app-mgr/app-manager/module_wasm_app.c b/core/app-mgr/app-manager/module_wasm_app.c index 7fbe8a53e..419739d53 100644 --- a/core/app-mgr/app-manager/module_wasm_app.c +++ b/core/app-mgr/app-manager/module_wasm_app.c @@ -17,12 +17,20 @@ #include "runtime_lib.h" /* Wasm app 4 magic bytes */ -static unsigned char wasm_app_magics[] = { (unsigned char) 0x00, - (unsigned char) 0x61, (unsigned char) 0x73, (unsigned char) 0x6d }; +static unsigned char wasm_app_magics[] = { + (unsigned char) 0x00, + (unsigned char) 0x61, + (unsigned char) 0x73, + (unsigned char) 0x6d +}; /* Wasm app 4 version bytes */ -static unsigned char wasm_app_version[] = { (unsigned char) 0x01, - (unsigned char) 0x00, (unsigned char) 0x00, (unsigned char) 0x00 }; +static unsigned char wasm_app_version[] = { + (unsigned char) 0x01, + (unsigned char) 0x00, + (unsigned char) 0x00, + (unsigned char) 0x00 +}; /* Wasm App Install Request Receiving Phase */ typedef enum wasm_app_install_req_recv_phase_t { @@ -73,7 +81,7 @@ static bool wasm_app_module_handle_host_url(void *queue_msg); static module_data *wasm_app_module_get_module_data(void *inst); static bool wasm_app_module_on_install_request_byte_arrive(uint8 ch, int request_total_size, - int *received_size); + int *received_size); static bool module_wasm_app_handle_install_msg(install_wasm_app_msg_t *message); static void destroy_wasm_sections_list(wasm_section_t *sections); @@ -84,14 +92,18 @@ int g_msg_type[Max_Msg_Callback] = { 0 }; message_type_handler_t g_msg_callbacks[Max_Msg_Callback] = { 0 }; #define Max_Cleanup_Callback 10 -static resource_cleanup_handler_t g_cleanup_callbacks[Max_Cleanup_Callback] = { - 0 }; +static resource_cleanup_handler_t +g_cleanup_callbacks[Max_Cleanup_Callback] = { 0 }; -module_interface wasm_app_module_interface = { wasm_app_module_init, - wasm_app_module_install, wasm_app_module_uninstall, - wasm_app_module_watchdog_kill, wasm_app_module_handle_host_url, - wasm_app_module_get_module_data, - wasm_app_module_on_install_request_byte_arrive }; +module_interface wasm_app_module_interface = { + wasm_app_module_init, + wasm_app_module_install, + wasm_app_module_uninstall, + wasm_app_module_watchdog_kill, + wasm_app_module_handle_host_url, + wasm_app_module_get_module_data, + wasm_app_module_on_install_request_byte_arrive +}; static unsigned align_uint(unsigned v, unsigned b) { @@ -99,6 +111,19 @@ static unsigned align_uint(unsigned v, unsigned b) return (v + m) & ~m; } +static wasm_function_inst_t +app_manager_lookup_function(const wasm_module_inst_t module_inst, + const char *name, const char *signature) +{ + wasm_function_inst_t func; + + func = wasm_runtime_lookup_function(module_inst, name, signature); + if (!func && name[0] == '_') + func = wasm_runtime_lookup_function(module_inst, name + 1, signature); + return func; +} + + static void app_instance_queue_callback(void *queue_msg, void *arg) { uint32 argv[2]; @@ -108,133 +133,157 @@ static void app_instance_queue_callback(void *queue_msg, void *arg) module_data *m_data = app_manager_get_module_data(Module_WASM_App, inst); int message_type = bh_message_type(queue_msg); - switch (message_type) { - case RESTFUL_REQUEST: { - request_t *request = (request_t *) bh_message_payload(queue_msg); - int size; - char *buffer; - int32 buffer_offset; + bh_assert(m_data); - app_manager_printf("App %s got request, url %s, action %d\n", - m_data->module_name, request->url, request->action); + if (message_type < BASE_EVENT_MAX) { + switch (message_type) { + case RESTFUL_REQUEST: { + request_t *request = (request_t *)bh_message_payload(queue_msg); + int size; + char *buffer; + int32 buffer_offset; - func_onRequest = wasm_runtime_lookup_function(inst, "_on_request", - "(i32i32)"); - if (!func_onRequest) { - app_manager_printf("Cannot find function onRequest\n"); - break; - } + app_manager_printf("App %s got request, url %s, action %d\n", + m_data->module_name, + request->url, + request->action); - buffer = pack_request(request, &size); - if (buffer == NULL) - break; + func_onRequest = app_manager_lookup_function(inst, + "_on_request", + "(i32i32)"); + if (!func_onRequest) { + app_manager_printf("Cannot find function onRequest\n"); + break; + } - buffer_offset = wasm_runtime_module_dup_data(inst, buffer, size); - if (buffer_offset == 0) { - app_manager_printf("Got exception running wasm code: %s\n", - wasm_runtime_get_exception(inst)); - wasm_runtime_clear_exception(inst); - free_req_resp_packet(buffer); - break; - } + buffer = pack_request(request, &size); + if (buffer == NULL) + break; - free_req_resp_packet(buffer); + buffer_offset = wasm_runtime_module_dup_data(inst, buffer, size); + if (buffer_offset == 0) { + app_manager_printf("Got exception running wasm code: %s\n", + wasm_runtime_get_exception(inst)); + wasm_runtime_clear_exception(inst); + free_req_resp_packet(buffer); + break; + } - argv[0] = (uint32) buffer_offset; - argv[1] = (uint32) size; + free_req_resp_packet(buffer); - if (!wasm_runtime_call_wasm(inst, NULL, func_onRequest, 2, argv)) { - app_manager_printf("Got exception running wasm code: %s\n", - wasm_runtime_get_exception(inst)); - wasm_runtime_clear_exception(inst); - wasm_runtime_module_free(inst, buffer_offset); - break; - } + argv[0] = (uint32) buffer_offset; + argv[1] = (uint32) size; - wasm_runtime_module_free(inst, buffer_offset); - app_manager_printf("Wasm app process request success.\n"); - break; - } - case RESTFUL_RESPONSE: { - response_t *response = (response_t *) bh_message_payload(queue_msg); - int size; - char *buffer; - int32 buffer_offset; + if (!wasm_runtime_call_wasm(inst, NULL, func_onRequest, 2, argv)) { + app_manager_printf("Got exception running wasm code: %s\n", + wasm_runtime_get_exception(inst)); + wasm_runtime_clear_exception(inst); + wasm_runtime_module_free(inst, buffer_offset); + break; + } - app_manager_printf("App %s got response_t,status %d\n", - m_data->module_name, response->status); - - wasm_function_inst_t func_onResponse = wasm_runtime_lookup_function( - inst, "_on_response", "(i32i32)"); - if (!func_onResponse) { - app_manager_printf("Cannot find function on_response\n"); - break; - } - - buffer = pack_response(response, &size); - if (buffer == NULL) - break; - - buffer_offset = wasm_runtime_module_dup_data(inst, buffer, size); - if (buffer_offset == 0) { - app_manager_printf("Got exception running wasm code: %s\n", - wasm_runtime_get_exception(inst)); - wasm_runtime_clear_exception(inst); - free_req_resp_packet(buffer); - break; - } - - free_req_resp_packet(buffer); - - argv[0] = (uint32) buffer_offset; - argv[1] = (uint32) size; - - if (!wasm_runtime_call_wasm(inst, NULL, func_onResponse, 2, argv)) { - app_manager_printf("Got exception running wasm code: %s\n", - wasm_runtime_get_exception(inst)); - wasm_runtime_clear_exception(inst); - wasm_runtime_module_free(inst, buffer_offset); - break; - } - - wasm_runtime_module_free(inst, buffer_offset); - app_manager_printf("Wasm app process response success.\n"); - break; - } - - case TIMER_EVENT_WASM: { - if (bh_message_payload(queue_msg)) { - /* Call Timer.callOnTimer() method */ - func_onTimer = wasm_runtime_lookup_function(inst, - "_on_timer_callback", "(i32)"); - - if (!func_onTimer) { - app_manager_printf("Cannot find function _on_timer_callback\n"); - break; + wasm_runtime_module_free(inst, buffer_offset); + app_manager_printf("Wasm app process request success.\n"); + break; } - unsigned int timer_id = (unsigned int)(uintptr_t) - bh_message_payload(queue_msg); - argv[0] = timer_id; - if (!wasm_runtime_call_wasm(inst, NULL, func_onTimer, 1, argv)) { - app_manager_printf("Got exception running wasm code: %s\n", - wasm_runtime_get_exception(inst)); - wasm_runtime_clear_exception(inst); + case RESTFUL_RESPONSE: { + wasm_function_inst_t func_onResponse; + response_t *response = (response_t *) bh_message_payload(queue_msg); + int size; + char *buffer; + int32 buffer_offset; + + app_manager_printf("App %s got response_t,status %d\n", + m_data->module_name, response->status); + + func_onResponse = + app_manager_lookup_function(inst, "_on_response", "(i32i32)"); + if (!func_onResponse) { + app_manager_printf("Cannot find function on_response\n"); + break; + } + + buffer = pack_response(response, &size); + if (buffer == NULL) + break; + + buffer_offset = wasm_runtime_module_dup_data(inst, buffer, size); + if (buffer_offset == 0) { + app_manager_printf("Got exception running wasm code: %s\n", + wasm_runtime_get_exception(inst)); + wasm_runtime_clear_exception(inst); + free_req_resp_packet(buffer); + break; + } + + free_req_resp_packet(buffer); + + argv[0] = (uint32) buffer_offset; + argv[1] = (uint32) size; + + if (!wasm_runtime_call_wasm(inst, NULL, func_onResponse, 2, argv)) { + app_manager_printf("Got exception running wasm code: %s\n", + wasm_runtime_get_exception(inst)); + wasm_runtime_clear_exception(inst); + wasm_runtime_module_free(inst, buffer_offset); + break; + } + + wasm_runtime_module_free(inst, buffer_offset); + app_manager_printf("Wasm app process response success.\n"); + break; + } + default: { + for (int i = 0; i < Max_Msg_Callback; i++) { + if (g_msg_type[i] == message_type) { + g_msg_callbacks[i](m_data, queue_msg); + return; + } + } + app_manager_printf("Invalid message type of WASM app queue message.\n"); + break; + } } - - break; } + else { + switch (message_type) { + case TIMER_EVENT_WASM: { + unsigned int timer_id; + if (bh_message_payload(queue_msg)) { + /* Call Timer.callOnTimer() method */ + func_onTimer = + app_manager_lookup_function(inst, + "_on_timer_callback", + "(i32)"); - default: { - for (int i = 0; i < Max_Msg_Callback; i++) { - if (g_msg_type[i] == message_type) { - g_msg_callbacks[i](m_data, queue_msg); - return; + if (!func_onTimer) { + app_manager_printf("Cannot find function _on_timer_callback\n"); + break; + } + timer_id = + (unsigned int)(uintptr_t)bh_message_payload(queue_msg); + argv[0] = timer_id; + if (!wasm_runtime_call_wasm(inst, NULL, func_onTimer, 1, argv)) { + app_manager_printf("Got exception running wasm code: %s\n", + wasm_runtime_get_exception(inst)); + wasm_runtime_clear_exception(inst); + } + } + break; } + default: { + for (int i = 0; i < Max_Msg_Callback; i++) { + if (g_msg_type[i] == message_type) { + g_msg_callbacks[i](m_data, queue_msg); + return; + } + } + app_manager_printf("Invalid message type of WASM app queue message.\n"); + break; + } + } - app_manager_printf("Invalid message type of WASM app queue message.\n"); - break; - } } } @@ -256,7 +305,7 @@ wasm_app_routine(void *arg) app_manager_printf("WASM app '%s' started\n", m_data->module_name); /* Call app's onInit() method */ - func_onInit = wasm_runtime_lookup_function(inst, "_on_init", "()"); + func_onInit = app_manager_lookup_function(inst, "_on_init", "()"); if (!func_onInit) { app_manager_printf("Cannot find function on_init().\n"); goto fail1; @@ -264,7 +313,7 @@ wasm_app_routine(void *arg) if (!wasm_runtime_call_wasm(inst, NULL, func_onInit, 0, NULL)) { printf("Got exception running WASM code: %s\n", - wasm_runtime_get_exception(inst)); + wasm_runtime_get_exception(inst)); wasm_runtime_clear_exception(inst); /* call on_destroy() in case some resources are opened in on_init() * and then exception thrown */ @@ -278,7 +327,7 @@ wasm_app_routine(void *arg) fail2: /* Call WASM app onDestroy() method if there is */ - func_onDestroy = wasm_runtime_lookup_function(inst, "_on_destroy", "()"); + func_onDestroy = app_manager_lookup_function(inst, "_on_destroy", "()"); if (func_onDestroy) wasm_runtime_call_wasm(inst, NULL, func_onDestroy, 0, NULL); @@ -341,8 +390,8 @@ static bool wasm_app_module_init(void) static bool wasm_app_module_install(request_t * msg) { - unsigned int m_data_size, wasm_app_aot_file_len, heap_size, timeout, timers, - err_size; + unsigned int m_data_size, wasm_app_aot_file_len, heap_size; + unsigned int timeout, timers, err_size; char *properties; int properties_offset, i; uint8 *wasm_app_aot_file; @@ -352,22 +401,25 @@ static bool wasm_app_module_install(request_t * msg) module_data *m_data; wasm_module_t module = NULL; wasm_module_inst_t inst = NULL; - char m_name[APP_NAME_MAX_LEN] = { 0 }, timeout_str[MAX_INT_STR_LEN] = { 0 }, - heap_size_str[MAX_INT_STR_LEN] = { 0 }, - timers_str[MAX_INT_STR_LEN] = { 0 }, err[256]; + char m_name[APP_NAME_MAX_LEN] = { 0 }; + char timeout_str[MAX_INT_STR_LEN] = { 0 }; + char heap_size_str[MAX_INT_STR_LEN] = { 0 }; + char timers_str[MAX_INT_STR_LEN] = { 0 }, err[256]; /* Useless sections after load */ - uint8 sections1[] = { SECTION_TYPE_USER, - SECTION_TYPE_TYPE, - SECTION_TYPE_IMPORT, - SECTION_TYPE_FUNC, - SECTION_TYPE_TABLE, - SECTION_TYPE_MEMORY, - SECTION_TYPE_GLOBAL, - SECTION_TYPE_EXPORT, - SECTION_TYPE_START, - SECTION_TYPE_ELEM, - /*SECTION_TYPE_CODE,*/ - /*SECTION_TYPE_DATA*/}; + uint8 sections1[] = { + SECTION_TYPE_USER, + SECTION_TYPE_TYPE, + SECTION_TYPE_IMPORT, + SECTION_TYPE_FUNC, + SECTION_TYPE_TABLE, + SECTION_TYPE_MEMORY, + SECTION_TYPE_GLOBAL, + SECTION_TYPE_EXPORT, + SECTION_TYPE_START, + SECTION_TYPE_ELEM, + /*SECTION_TYPE_CODE,*/ + /*SECTION_TYPE_DATA*/ + }; /* Useless sections after instantiate */ uint8 sections2[] = { SECTION_TYPE_DATA }; @@ -375,8 +427,7 @@ static bool wasm_app_module_install(request_t * msg) /* Check payload */ if (!msg->payload || msg->payload_len == 0) { - SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: invalid wasm file."); + SEND_ERR_RESPONSE(msg->mid, "Install WASM app failed: invalid wasm file."); return false; } @@ -387,24 +438,22 @@ static bool wasm_app_module_install(request_t * msg) return false; properties = msg->url + properties_offset; find_key_value(properties, strlen(properties), "name", m_name, - sizeof(m_name) - 1, '&'); + sizeof(m_name) - 1, '&'); if (strlen(m_name) == 0) { - SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: invalid app name."); + SEND_ERR_RESPONSE(msg->mid, "Install WASM app failed: invalid app name."); return false; } if (app_manager_lookup_module_data(m_name)) { - SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: app already installed."); + SEND_ERR_RESPONSE(msg->mid, "Install WASM app failed: app already installed."); return false; } /* Parse heap size */ heap_size = APP_HEAP_SIZE_DEFAULT; find_key_value(properties, strlen(properties), "heap", heap_size_str, - sizeof(heap_size_str) - 1, '&'); + sizeof(heap_size_str) - 1, '&'); if (strlen(heap_size_str) > 0) { heap_size = atoi(heap_size_str); if (heap_size < APP_HEAP_SIZE_MIN) @@ -421,19 +470,20 @@ static bool wasm_app_module_install(request_t * msg) wasm_app_aot_file = (uint8 *) msg->payload; wasm_app_aot_file_len = msg->payload_len; inst = wasm_runtime_load_aot(wasm_app_aot_file, wasm_app_aot_file_len, - heap_size, err, err_size); + heap_size, err, err_size); if (!inst) { SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: load wasm aot binary failed."); + "Install WASM app failed: load wasm aot binary failed."); return false; } - } else if (package_type == Wasm_Module_Bytecode) { + } + else if (package_type == Wasm_Module_Bytecode) { wasm_app_file = (wasm_app_file_t *) msg->payload; module = wasm_runtime_load_from_sections(wasm_app_file->sections, err, - err_size); + err_size); if (!module) { SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: load WASM file failed."); + "Install WASM app failed: load WASM file failed."); printf("error: %s\n", err); destroy_wasm_sections_list(wasm_app_file->sections); return false; @@ -442,7 +492,7 @@ static bool wasm_app_module_install(request_t * msg) /* Destroy useless sections from list after load */ for (i = 0; i < sizeof(sections1); i++) destroy_wasm_section_from_list(&wasm_app_file->sections, - sections1[i]); + sections1[i]); inst = wasm_runtime_instantiate(module, 0, heap_size, err, err_size); if (!inst) { @@ -457,11 +507,12 @@ static bool wasm_app_module_install(request_t * msg) /* Destroy useless sections from list after instantiate */ for (i = 0; i < sizeof(sections2); i++) destroy_wasm_section_from_list(&wasm_app_file->sections, - sections2[i]); + sections2[i]); - } else { + } + else { SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: invalid wasm package type."); + "Install WASM app failed: invalid wasm package type."); return false; } @@ -470,8 +521,7 @@ static bool wasm_app_module_install(request_t * msg) m_data_size = align_uint(m_data_size, 4); m_data = bh_malloc(m_data_size + sizeof(wasm_data)); if (!m_data) { - SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: allocate memory failed."); + SEND_ERR_RESPONSE(msg->mid, "Install WASM app failed: allocate memory failed."); goto fail; } memset(m_data, 0, m_data_size + sizeof(wasm_data)); @@ -490,7 +540,7 @@ static bool wasm_app_module_install(request_t * msg) /* Set module data - execution timeout */ timeout = DEFAULT_WATCHDOG_INTERVAL; find_key_value(properties, strlen(properties), "wd", timeout_str, - sizeof(timeout_str) - 1, '&'); + sizeof(timeout_str) - 1, '&'); if (strlen(timeout_str) > 0) timeout = atoi(timeout_str); m_data->timeout = timeout; @@ -498,8 +548,7 @@ static bool wasm_app_module_install(request_t * msg) /* Set module data - create queue */ m_data->queue = bh_queue_create(); if (!m_data->queue) { - SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: create app queue failed."); + SEND_ERR_RESPONSE(msg->mid, "Install WASM app failed: create app queue failed."); goto fail; } @@ -522,24 +571,23 @@ static bool wasm_app_module_install(request_t * msg) m_data->timer_ctx = create_wasm_timer_ctx(m_data->id, timers); if (!m_data->timer_ctx) { SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: create app timers failed."); + "Install WASM app failed: create app timers failed."); goto fail; } /* Initialize watchdog timer */ if (!watchdog_timer_init(m_data)) { SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: create app watchdog timer failed."); + "Install WASM app failed: create app watchdog timer failed."); goto fail; } /* Create WASM app thread. */ if (vm_thread_create(&wasm_app_data->thread_id, wasm_app_routine, - (void*) m_data, APP_THREAD_STACK_SIZE_DEFAULT) != 0) { + (void*) m_data, APP_THREAD_STACK_SIZE_DEFAULT) != 0) { module_data_list_remove(m_data); SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: create app threadf failed."); - + "Install WASM app failed: create app threadf failed."); goto fail; } @@ -551,7 +599,8 @@ static bool wasm_app_module_install(request_t * msg) return true; - fail: if (m_data) +fail: + if (m_data) release_module(m_data); wasm_runtime_deinstantiate(inst); @@ -580,11 +629,10 @@ static bool wasm_app_module_uninstall(request_t *msg) return false; properties = msg->url + properties_offset; find_key_value(properties, strlen(properties), "name", m_name, - sizeof(m_name) - 1, '&'); + sizeof(m_name) - 1, '&'); if (strlen(m_name) == 0) { - SEND_ERR_RESPONSE(msg->mid, - "Uninstall WASM app failed: invalid app name."); + SEND_ERR_RESPONSE(msg->mid, "Uninstall WASM app failed: invalid app name."); return false; } @@ -595,14 +643,13 @@ static bool wasm_app_module_uninstall(request_t *msg) } if (m_data->module_type != Module_WASM_App) { - SEND_ERR_RESPONSE(msg->mid, - "Uninstall WASM app failed: invalid module type."); + SEND_ERR_RESPONSE(msg->mid, "Uninstall WASM app failed: invalid module type."); return false; } if (m_data->wd_timer.is_interrupting) { SEND_ERR_RESPONSE(msg->mid, - "Uninstall WASM app failed: app is being interrupted by watchdog."); + "Uninstall WASM app failed: app is being interrupted by watchdog."); return false; } @@ -646,7 +693,7 @@ static void wasm_app_module_watchdog_kill(module_data *m_data) } bool wasm_register_msg_callback(int message_type, - message_type_handler_t message_handler) + message_type_handler_t message_handler) { int i; int freeslot = -1; @@ -684,26 +731,27 @@ bool wasm_register_cleanup_callback(resource_cleanup_handler_t handler) return false; } -#define RECV_INTEGER(value, next_phase) do{ \ - unsigned char *p = (unsigned char *)&value; \ - p[recv_ctx.size_in_phase++] = ch; \ - if (recv_ctx.size_in_phase == sizeof(value)) { \ - if (sizeof(value) == 4) \ - value = ntohl(value); \ - else if (sizeof(value) == 2) \ - value = ntohs(value); \ - recv_ctx.phase = next_phase; \ - recv_ctx.size_in_phase = 0; \ - } \ -} while(0) +#define RECV_INTEGER(value, next_phase) do { \ + unsigned char *p = (unsigned char *)&value; \ + p[recv_ctx.size_in_phase++] = ch; \ + if (recv_ctx.size_in_phase == sizeof(value)) { \ + if (sizeof(value) == 4) \ + value = ntohl(value); \ + else if (sizeof(value) == 2) \ + value = ntohs(value); \ + recv_ctx.phase = next_phase; \ + recv_ctx.size_in_phase = 0; \ + } \ + } while(0) /* return: * 1: whole wasm app arrived * 0: one valid byte arrived * -1: fail to process the byte arrived, e.g. allocate memory fail */ -static bool wasm_app_module_on_install_request_byte_arrive(uint8 ch, - int request_total_size, int *received_size) +static bool +wasm_app_module_on_install_request_byte_arrive(uint8 ch, int request_total_size, + int *received_size) { if (recv_ctx.phase == Phase_Req_Ver) { recv_ctx.phase = Phase_Req_Ver; @@ -719,49 +767,57 @@ static bool wasm_app_module_on_install_request_byte_arrive(uint8 ch, return false; recv_ctx.phase = Phase_Req_Action; return true; - } else if (recv_ctx.phase == Phase_Req_Action) { + } + else if (recv_ctx.phase == Phase_Req_Action) { recv_ctx.message.request_action = ch; recv_ctx.phase = Phase_Req_Fmt; recv_ctx.size_in_phase = 0; return true; - } else if (recv_ctx.phase == Phase_Req_Fmt) { + } + else if (recv_ctx.phase == Phase_Req_Fmt) { RECV_INTEGER(recv_ctx.message.request_fmt, Phase_Req_Mid); return true; - } else if (recv_ctx.phase == Phase_Req_Mid) { + } + else if (recv_ctx.phase == Phase_Req_Mid) { RECV_INTEGER(recv_ctx.message.request_mid, Phase_Req_Sender); return true; - } else if (recv_ctx.phase == Phase_Req_Sender) { + } + else if (recv_ctx.phase == Phase_Req_Sender) { RECV_INTEGER(recv_ctx.message.request_sender, Phase_Req_Url_Len); return true; - } else if (recv_ctx.phase == Phase_Req_Url_Len) { + } + else if (recv_ctx.phase == Phase_Req_Url_Len) { unsigned char *p = (unsigned char *) &recv_ctx.message.request_url_len; p[recv_ctx.size_in_phase++] = ch; - if (recv_ctx.size_in_phase - == sizeof(recv_ctx.message.request_url_len)) { - recv_ctx.message.request_url_len = ntohs( - recv_ctx.message.request_url_len); - recv_ctx.message.request_url = bh_malloc( - recv_ctx.message.request_url_len + 1); + if (recv_ctx.size_in_phase == + sizeof(recv_ctx.message.request_url_len)) { + recv_ctx.message.request_url_len = + ntohs(recv_ctx.message.request_url_len); + recv_ctx.message.request_url = + bh_malloc(recv_ctx.message.request_url_len + 1); if (NULL == recv_ctx.message.request_url) goto fail; memset(recv_ctx.message.request_url, 0, - recv_ctx.message.request_url_len + 1); + recv_ctx.message.request_url_len + 1); recv_ctx.phase = Phase_Req_Payload_Len; recv_ctx.size_in_phase = 0; } return true; - } else if (recv_ctx.phase == Phase_Req_Payload_Len) { + } + else if (recv_ctx.phase == Phase_Req_Payload_Len) { RECV_INTEGER(recv_ctx.message.wasm_app_size, Phase_Req_Url); return true; - } else if (recv_ctx.phase == Phase_Req_Url) { + } + else if (recv_ctx.phase == Phase_Req_Url) { recv_ctx.message.request_url[recv_ctx.size_in_phase++] = ch; if (recv_ctx.size_in_phase == recv_ctx.message.request_url_len) { recv_ctx.phase = Phase_Wasm_Magic; recv_ctx.size_in_phase = 0; } return true; - } else if (recv_ctx.phase == Phase_Wasm_Magic) { + } + else if (recv_ctx.phase == Phase_Wasm_Magic) { /* start to receive wasm app binary */ unsigned char *p = (unsigned char *) &recv_ctx.message.wasm_app_binary.magic; @@ -771,14 +827,14 @@ static bool wasm_app_module_on_install_request_byte_arrive(uint8 ch, else goto fail; - if (recv_ctx.size_in_phase - == sizeof(recv_ctx.message.wasm_app_binary.magic)) { + if (recv_ctx.size_in_phase == + sizeof(recv_ctx.message.wasm_app_binary.magic)) { recv_ctx.phase = Phase_Wasm_Version; recv_ctx.size_in_phase = 0; } - return true; - } else if (recv_ctx.phase == Phase_Wasm_Version) { + } + else if (recv_ctx.phase == Phase_Wasm_Version) { unsigned char *p = (unsigned char *) &recv_ctx.message.wasm_app_binary.version; @@ -787,14 +843,14 @@ static bool wasm_app_module_on_install_request_byte_arrive(uint8 ch, else goto fail; - if (recv_ctx.size_in_phase - == sizeof(recv_ctx.message.wasm_app_binary.version)) { + if (recv_ctx.size_in_phase == + sizeof(recv_ctx.message.wasm_app_binary.version)) { recv_ctx.phase = Phase_Wasm_Section_Type; recv_ctx.size_in_phase = 0; } - return true; - } else if (recv_ctx.phase == Phase_Wasm_Section_Type) { + } + else if (recv_ctx.phase == Phase_Wasm_Section_Type) { wasm_section_t *new_section; if (!(new_section = (wasm_section_t *) bh_malloc(sizeof(wasm_section_t)))) @@ -808,7 +864,8 @@ static bool wasm_app_module_on_install_request_byte_arrive(uint8 ch, if (NULL == recv_ctx.message.wasm_app_binary.sections) { recv_ctx.message.wasm_app_binary.sections = new_section; recv_ctx.message.wasm_app_binary.section_end = new_section; - } else { + } + else { recv_ctx.message.wasm_app_binary.section_end->next = new_section; recv_ctx.message.wasm_app_binary.section_end = new_section; } @@ -817,7 +874,8 @@ static bool wasm_app_module_on_install_request_byte_arrive(uint8 ch, recv_ctx.size_in_phase = 0; return true; - } else if (recv_ctx.phase == Phase_Wasm_Section_Size) { + } + else if (recv_ctx.phase == Phase_Wasm_Section_Size) { /* the last section is the current receiving one */ wasm_section_t *section = recv_ctx.message.wasm_app_binary.section_end; uint32 byte; @@ -830,8 +888,8 @@ static bool wasm_app_module_on_install_request_byte_arrive(uint8 ch, << recv_ctx.size_in_phase * 7); recv_ctx.size_in_phase++; /* check leab128 overflow for uint32 value */ - if (recv_ctx.size_in_phase - > (sizeof(section->section_body_size) * 8 + 7 - 1) / 7) { + if (recv_ctx.size_in_phase > + (sizeof(section->section_body_size) * 8 + 7 - 1) / 7) { app_manager_printf(" LEB overflow when parsing section size\n"); goto fail; } @@ -845,7 +903,8 @@ static bool wasm_app_module_on_install_request_byte_arrive(uint8 ch, } return true; - } else if (recv_ctx.phase == Phase_Wasm_Section_Content) { + } + else if (recv_ctx.phase == Phase_Wasm_Section_Content) { /* the last section is the current receiving one */ wasm_section_t *section = recv_ctx.message.wasm_app_binary.section_end; @@ -861,9 +920,11 @@ static bool wasm_app_module_on_install_request_byte_arrive(uint8 ch, recv_ctx.message.request_url = NULL; memset(&recv_ctx, 0, sizeof(recv_ctx)); return true; - } else + } + else goto fail; - } else { + } + else { recv_ctx.phase = Phase_Wasm_Section_Type; recv_ctx.size_in_phase = 0; return true; @@ -873,7 +934,8 @@ static bool wasm_app_module_on_install_request_byte_arrive(uint8 ch, return true; } - fail: if (recv_ctx.message.wasm_app_binary.sections != NULL) { +fail: + if (recv_ctx.message.wasm_app_binary.sections != NULL) { destroy_wasm_sections_list(recv_ctx.message.wasm_app_binary.sections); recv_ctx.message.wasm_app_binary.sections = NULL; } @@ -915,13 +977,14 @@ static bool module_wasm_app_handle_install_msg(install_wasm_app_msg_t *message) /* Request payload is set to wasm_app_file_t struct, * but not whole app buffer */ - memcpy(request->payload, &message->wasm_app_binary, request->payload_len); + bh_memcpy_s(request->payload, request->payload_len, + &message->wasm_app_binary, request->payload_len); /* Since it's a wasm app install request, so directly post to app-mgr's * queue. The benefit is that section list can be freed when the msg * failed to post to app-mgr's queue. The defect is missing url check. */ if (!(msg = bh_new_msg(RESTFUL_REQUEST, request, sizeof(*request), - request_cleaner))) { + request_cleaner))) { request_cleaner(request); return false; } @@ -970,9 +1033,11 @@ static void destroy_wasm_section_from_list(wasm_section_t **sections, int type) bh_free(cur->section_body); bh_free(cur); break; - } else { + } + else { prev = cur; } cur = next; } } + diff --git a/core/app-mgr/app-mgr-shared/app_manager_export.h b/core/app-mgr/app-mgr-shared/app_manager_export.h index 91ea96aba..cf9614e03 100644 --- a/core/app-mgr/app-mgr-shared/app_manager_export.h +++ b/core/app-mgr/app-mgr-shared/app_manager_export.h @@ -16,6 +16,12 @@ extern "C" { #endif +/* Special module IDs */ +#define ID_HOST -3 +#define ID_APP_MGR -2 +/* Invalid module ID */ +#define ID_NONE (uint32)-1 + struct attr_container_t; /* Queue message type */ @@ -56,6 +62,7 @@ typedef struct watchdog_timer { typedef struct module_data { struct module_data *next; + /* ID of the module */ uint32 id; /* Type of the module */ diff --git a/core/iwasm/app-samples/hello-world/build.sh b/core/iwasm/app-samples/hello-world/build.sh index 1509e8158..822ecc867 100755 --- a/core/iwasm/app-samples/hello-world/build.sh +++ b/core/iwasm/app-samples/hello-world/build.sh @@ -1,6 +1,10 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -emcc -g -O3 *.c -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \ - -s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 -o test.wasm +clang-8 --target=wasm32 -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -Wl,--allow-undefined, \ + -Wl,--export=main, \ + -Wl,--no-threads,--strip-all,--no-entry \ + -nostdlib -o test.wasm *.c #./jeffdump -o test_wasm.h -n wasm_test_file test.wasm diff --git a/core/iwasm/app-samples/hello-world/main.c b/core/iwasm/app-samples/hello-world/main.c index 791e1d025..d392fb1f8 100644 --- a/core/iwasm/app-samples/hello-world/main.c +++ b/core/iwasm/app-samples/hello-world/main.c @@ -20,7 +20,7 @@ int main(int argc, char **argv) printf("buf ptr: %p\n", buf); - sprintf(buf, "%s", "1234\n"); + snprintf(buf, 1024, "%s", "1234\n"); printf("buf: %s", buf); free(buf); diff --git a/core/iwasm/app-samples/smart-light/build.sh b/core/iwasm/app-samples/smart-light/build.sh index e6dab5fc5..d921f23c1 100755 --- a/core/iwasm/app-samples/smart-light/build.sh +++ b/core/iwasm/app-samples/smart-light/build.sh @@ -1,6 +1,10 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -emcc -g -O3 *.c -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \ - -s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 -o test.wasm +clang-8 --target=wasm32 -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -Wl,--allow-undefined, \ + -Wl,--export=main, \ + -Wl,--no-threads,--strip-all,--no-entry \ + -nostdlib -o test.wasm *.c #./jeffdump -o ../test_wasm.h -n wasm_test_file test.wasm diff --git a/core/iwasm/lib/native-interface/restful_utils.c b/core/iwasm/lib/native-interface/restful_utils.c index d0ae1b3cb..0a31a77c0 100644 --- a/core/iwasm/lib/native-interface/restful_utils.c +++ b/core/iwasm/lib/native-interface/restful_utils.c @@ -180,7 +180,8 @@ request_t *clone_request(request_t *request) return req; - fail: request_cleaner(req); +fail: + request_cleaner(req); return NULL; } @@ -225,7 +226,8 @@ response_t * clone_response(response_t * response) } return clone; - fail: response_cleaner(clone); +fail: + response_cleaner(clone); return NULL; } diff --git a/core/iwasm/lib/native/base/request_response.c b/core/iwasm/lib/native/base/request_response.c index 97491e507..e9b44d69c 100644 --- a/core/iwasm/lib/native/base/request_response.c +++ b/core/iwasm/lib/native/base/request_response.c @@ -6,6 +6,7 @@ #include "app_manager_export.h" #include "coap_ext.h" #include "wasm_export.h" +#include "bh_assert.h" extern void module_request_handler(request_t *request, void *user_data); @@ -47,6 +48,7 @@ wasm_register_resource(wasm_module_inst_t module_inst, int32 url_offset) if (url != NULL) { unsigned int mod_id = app_manager_get_module_id(Module_WASM_App, module_inst); + bh_assert(mod_id != ID_NONE); am_register_resource(url, module_request_handler, mod_id); } } @@ -73,6 +75,7 @@ wasm_post_request(wasm_module_inst_t module_inst, // set sender to help dispatch the response to the sender ap unsigned int mod_id = app_manager_get_module_id(Module_WASM_App, module_inst); + bh_assert(mod_id != ID_NONE); req->sender = mod_id; if (req->action == COAP_EVENT) { @@ -98,6 +101,7 @@ wasm_sub_event(wasm_module_inst_t module_inst, int32 url_offset) unsigned int mod_id = app_manager_get_module_id(Module_WASM_App, module_inst); + bh_assert(mod_id != ID_NONE); am_register_event(url, mod_id); } } diff --git a/core/iwasm/lib/native/base/timer_wrapper.c b/core/iwasm/lib/native/base/timer_wrapper.c index ce9bacd9a..a18b4753d 100644 --- a/core/iwasm/lib/native/base/timer_wrapper.c +++ b/core/iwasm/lib/native/base/timer_wrapper.c @@ -143,27 +143,34 @@ timer_id_t wasm_create_timer(wasm_module_inst_t module_inst, int interval, bool is_period, bool auto_start) { - return sys_create_timer(get_wasm_timer_ctx(module_inst), interval, is_period, - auto_start); + timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst); + bh_assert(timer_ctx); + return sys_create_timer(timer_ctx, interval, is_period, auto_start); } void wasm_timer_destroy(wasm_module_inst_t module_inst, timer_id_t timer_id) { - sys_timer_destroy(get_wasm_timer_ctx(module_inst), timer_id); + timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst); + bh_assert(timer_ctx); + sys_timer_destroy(timer_ctx, timer_id); } void wasm_timer_cancel(wasm_module_inst_t module_inst, timer_id_t timer_id) { - sys_timer_cancel(get_wasm_timer_ctx(module_inst), timer_id); + timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst); + bh_assert(timer_ctx); + sys_timer_cancel(timer_ctx, timer_id); } void wasm_timer_restart(wasm_module_inst_t module_inst, timer_id_t timer_id, int interval) { - sys_timer_restart(get_wasm_timer_ctx(module_inst), timer_id, interval); + timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst); + bh_assert(timer_ctx); + sys_timer_restart(timer_ctx, timer_id, interval); } extern uint32 get_sys_tick_ms(); diff --git a/core/iwasm/lib/native/extension/connection/linux/conn_uart.c b/core/iwasm/lib/native/extension/connection/linux/conn_uart.c index 06318c2c3..1f5c4e767 100644 --- a/core/iwasm/lib/native/extension/connection/linux/conn_uart.c +++ b/core/iwasm/lib/native/extension/connection/linux/conn_uart.c @@ -60,7 +60,7 @@ int uart_open(char* device, int baudrate) uart_fd = open(device, O_RDWR | O_NOCTTY); - if (uart_fd <= 0) + if (uart_fd < 0) return -1; memset(&uart_term, 0, sizeof(uart_term)); diff --git a/core/iwasm/lib/native/extension/connection/linux/conn_udp.c b/core/iwasm/lib/native/extension/connection/linux/conn_udp.c index e7093a71c..9d370475a 100644 --- a/core/iwasm/lib/native/extension/connection/linux/conn_udp.c +++ b/core/iwasm/lib/native/extension/connection/linux/conn_udp.c @@ -26,8 +26,10 @@ int udp_open(uint16 port) addr.sin_port = htons(port); ret = bind(sock, (struct sockaddr*)&addr, sizeof(addr)); - if (ret == -1) + if (ret == -1) { + close(sock); return -1; + } /* Put the socket in non-blocking mode */ if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK) < 0) { diff --git a/core/iwasm/lib/native/extension/connection/linux/connection_mgr.c b/core/iwasm/lib/native/extension/connection/linux/connection_mgr.c index 786906668..6b9c3a455 100644 --- a/core/iwasm/lib/native/extension/connection/linux/connection_mgr.c +++ b/core/iwasm/lib/native/extension/connection/linux/connection_mgr.c @@ -17,6 +17,8 @@ #include "conn_tcp.h" #include "conn_udp.h" #include "conn_uart.h" +#include "bh_common.h" +#include "bh_assert.h" #include #include @@ -214,6 +216,7 @@ static uint32 _conn_open(wasm_module_inst_t module_inst, struct epoll_event ev; uint32 module_id = app_manager_get_module_id(Module_WASM_App, module_inst); + bh_assert(module_id != ID_NONE); if (get_app_conns_num(module_id) >= MAX_CONNECTION_PER_APP) return -1; @@ -242,7 +245,7 @@ static uint32 _conn_open(wasm_module_inst_t module_inst, port = attr_container_get_as_uint16(args, "port"); /* Connect to TCP server */ - if ((fd = tcp_open(address, port)) == -1) + if (!address || (fd = tcp_open(address, port)) == -1) goto fail; } else if (conn->type == CONN_TYPE_UDP) { @@ -269,9 +272,10 @@ static uint32 _conn_open(wasm_module_inst_t module_inst, baud = attr_container_get_as_int(args, "baudrate"); /* Open device */ - if ((fd = uart_open(device, baud)) == -1) + if (!device || (fd = uart_open(device, baud)) == -1) goto fail; - + } else { + goto fail; } conn->fd = fd; @@ -345,7 +349,8 @@ static bool _conn_config(uint32 handle, attr_container_t *cfg) if (!attr_container_contain_key(cfg, "address") || !attr_container_contain_key(cfg, "port")) return false; - address = attr_container_get_as_string(cfg, "address"); + if (!(address = attr_container_get_as_string(cfg, "address"))) + return false; port = attr_container_get_as_uint16(cfg, "port"); if (conn->arg == NULL) { @@ -409,7 +414,7 @@ static void post_msg_to_module(sys_connection_t *conn, bh_free(conn_data_event); return; } - memcpy(data_copy, data, len); + bh_memcpy_s(data_copy, len, data, len); } memset(conn_data_event, 0, sizeof(*conn_data_event)); diff --git a/core/iwasm/lib/native/extension/connection/zephyr/connection_mgr.cmake b/core/iwasm/lib/native/extension/connection/zephyr/connection_mgr.cmake new file mode 100644 index 000000000..c8f2b487e --- /dev/null +++ b/core/iwasm/lib/native/extension/connection/zephyr/connection_mgr.cmake @@ -0,0 +1,13 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (WASM_LIB_CONN_MGR_DIR ${CMAKE_CURRENT_LIST_DIR}) + +include_directories(${WASM_LIB_CONN_MGR_DIR}) + + +file (GLOB_RECURSE source_all ${WASM_LIB_CONN_MGR_DIR}/*.c) + +set (WASM_LIB_CONN_MGR_SOURCE ${source_all}) + + diff --git a/core/iwasm/lib/native/extension/gui/wasm_lib_gui.cmake b/core/iwasm/lib/native/extension/gui/wasm_lib_gui.cmake index 3658cd442..eb57b3fa9 100644 --- a/core/iwasm/lib/native/extension/gui/wasm_lib_gui.cmake +++ b/core/iwasm/lib/native/extension/gui/wasm_lib_gui.cmake @@ -5,7 +5,10 @@ set (WASM_LIB_GUI_DIR ${CMAKE_CURRENT_LIST_DIR}) set (THIRD_PARTY_DIR ${WASM_LIB_GUI_DIR}/../../../3rdparty) -include_directories(${WASM_LIB_GUI_DIR} ${THIRD_PARTY_DIR} ${THIRD_PARTY_DIR}/lvgl) +include_directories(${WASM_LIB_GUI_DIR} + ${THIRD_PARTY_DIR} + ${THIRD_PARTY_DIR}/lvgl + ${THIRD_PARTY_DIR}/lvgl/src) file (GLOB_RECURSE lvgl_source ${THIRD_PARTY_DIR}/lvgl/*.c) file (GLOB_RECURSE wrapper_source ${WASM_LIB_GUI_DIR}/*.c) diff --git a/core/iwasm/lib/native/extension/gui/wgl_list_wrapper.c b/core/iwasm/lib/native/extension/gui/wgl_list_wrapper.c index 8e6c601dc..5cd6c7a2a 100644 --- a/core/iwasm/lib/native/extension/gui/wgl_list_wrapper.c +++ b/core/iwasm/lib/native/extension/gui/wgl_list_wrapper.c @@ -7,6 +7,7 @@ #include "lvgl.h" #include "module_wasm_app.h" #include "wgl_native_utils.h" +#include "bh_assert.h" /* ------------------------------------------------------------------------- * List widget native function wrappers @@ -24,16 +25,17 @@ lv_list_add_btn_wrapper(wasm_module_inst_t module_inst, { uint32 btn_obj_id; lv_obj_t *btn; + uint32 mod_id; btn = lv_list_add_btn(list, NULL, text); if (btn == NULL) return 0; - if (wgl_native_add_object(btn, - app_manager_get_module_id(Module_WASM_App, - module_inst), - &btn_obj_id)) + mod_id = app_manager_get_module_id(Module_WASM_App, module_inst); + bh_assert(mod_id != ID_NONE); + + if (wgl_native_add_object(btn, mod_id, &btn_obj_id)) return btn_obj_id; /* success return */ return 0; diff --git a/core/iwasm/lib/native/extension/gui/wgl_native_utils.c b/core/iwasm/lib/native/extension/gui/wgl_native_utils.c index d07b13a87..5fdaffdd7 100644 --- a/core/iwasm/lib/native/extension/gui/wgl_native_utils.c +++ b/core/iwasm/lib/native/extension/gui/wgl_native_utils.c @@ -4,7 +4,7 @@ #include "lvgl.h" #include "module_wasm_app.h" #include "wasm_export.h" -#include "wasm_assert.h" +#include "bh_assert.h" #include @@ -17,7 +17,8 @@ uint32 wgl_native_wigdet_create(int8 widget_type, lv_obj_t *par, lv_obj_t *copy, wasm_module_inst_t module_inst) { uint32 obj_id; - lv_obj_t *wigdet; + lv_obj_t *wigdet = NULL; + uint32 mod_id; //TODO: limit total widget number @@ -38,10 +39,10 @@ uint32 wgl_native_wigdet_create(int8 widget_type, lv_obj_t *par, lv_obj_t *copy, if (wigdet == NULL) return 0; - if (wgl_native_add_object(wigdet, - app_manager_get_module_id(Module_WASM_App, - module_inst), - &obj_id)) + mod_id = app_manager_get_module_id(Module_WASM_App, module_inst); + bh_assert(mod_id != ID_NONE); + + if (wgl_native_add_object(wigdet, mod_id, &obj_id)) return obj_id; /* success return */ return 0; @@ -49,7 +50,7 @@ uint32 wgl_native_wigdet_create(int8 widget_type, lv_obj_t *par, lv_obj_t *copy, static void invokeNative(intptr_t argv[], uint32 argc, void (*native_code)()) { - wasm_assert(argc >= 1); + bh_assert(argc >= 1); switch(argc) { case 1: diff --git a/core/iwasm/lib/native/extension/gui/wgl_obj_wrapper.c b/core/iwasm/lib/native/extension/gui/wgl_obj_wrapper.c index 14bad3a2d..d84a4e84a 100644 --- a/core/iwasm/lib/native/extension/gui/wgl_obj_wrapper.c +++ b/core/iwasm/lib/native/extension/gui/wgl_obj_wrapper.c @@ -50,7 +50,10 @@ static void app_mgr_object_event_callback(module_data *m_data, bh_message_t msg) return; func_on_object_event = wasm_runtime_lookup_function(inst, "_on_widget_event", - "(i32i32)"); + "(i32i32)"); + if (!func_on_object_event) + func_on_object_event = wasm_runtime_lookup_function(inst, "on_widget_event", + "(i32i32)"); if (!func_on_object_event) { printf("Cannot find function _on_object_event\n"); return; diff --git a/core/iwasm/lib/native/extension/sensor/runtime_sensor.c b/core/iwasm/lib/native/extension/sensor/runtime_sensor.c index 1a01993c9..41e6ed653 100644 --- a/core/iwasm/lib/native/extension/sensor/runtime_sensor.c +++ b/core/iwasm/lib/native/extension/sensor/runtime_sensor.c @@ -8,6 +8,8 @@ #include "module_wasm_app.h" #include "bh_thread.h" #include "bh_time.h" +#include "bh_common.h" +#include "bh_assert.h" static sys_sensor_t * g_sys_sensors = NULL; static int g_sensor_id_max = 0; @@ -59,7 +61,8 @@ wasm_sensor_callback(void *client, uint32 sensor_id, void *user_data) return; /* multiple sensor clients may use/free the sensor data, so make a copy */ - memcpy(sensor_data_clone, sensor_data, sensor_data_len); + bh_memcpy_s(sensor_data_clone, sensor_data_len, + sensor_data, sensor_data_len); sensor_event = (sensor_event_data_t *)bh_malloc(sizeof(*sensor_event)); if (sensor_event == NULL) { @@ -97,6 +100,7 @@ wasm_sensor_config(wasm_module_inst_t module_inst, unsigned int mod_id = app_manager_get_module_id(Module_WASM_App, module_inst); + bh_assert(mod_id != ID_NONE); vm_mutex_lock(&s->lock); @@ -147,6 +151,7 @@ wasm_sensor_open(wasm_module_inst_t module_inst, unsigned int mod_id = app_manager_get_module_id(Module_WASM_App, module_inst); + bh_assert(mod_id != ID_NONE); vm_mutex_lock(&s->lock); @@ -219,6 +224,8 @@ wasm_sensor_close(wasm_module_inst_t module_inst, uint32 sensor) sensor_obj_t s = find_sys_sensor_id(sensor); sensor_client_t *c; + bh_assert(mod_id != ID_NONE); + if (s == NULL) return false; diff --git a/core/iwasm/lib/native/libc/libc_wrapper.c b/core/iwasm/lib/native/libc/libc_wrapper.c index 22f848f70..671716651 100644 --- a/core/iwasm/lib/native/libc/libc_wrapper.c +++ b/core/iwasm/lib/native/libc/libc_wrapper.c @@ -7,6 +7,10 @@ #include "wasm_export.h" #include "wasm_log.h" #include "wasm_platform_log.h" +#include "bh_common.h" +#if WASM_ENABLE_WASI != 0 +#include "wasi_wrapper.h" +#endif void wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); @@ -52,7 +56,7 @@ enum pad_type { typedef char *_va_list; #define _INTSIZEOF(n) \ - ((sizeof(n) + 3) & ~3) + (((uint32)sizeof(n) + 3) & (uint32)~3) #define _va_arg(ap, t) \ (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t))) @@ -86,7 +90,7 @@ _printf_hex_uint(out_func_t out, void *ctx, if (nibble || found_largest_digit || size == 1) { found_largest_digit = 1; - nibble += nibble > 9 ? 87 : 48; + nibble = (char)(nibble + (nibble > 9 ? 87 : 48)); out((int) nibble, ctx); digits++; continue; @@ -250,7 +254,7 @@ _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, d = -d; min_width--; } - _printf_dec_uint(out, ctx, d, padding, min_width); + _printf_dec_uint(out, ctx, (uint32)d, padding, min_width); break; } case 'u': { @@ -301,8 +305,8 @@ _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, char *start; int32 s_offset; - CHECK_VA_ARG(ap, uint32); - s_offset = _va_arg(ap, uint32); + CHECK_VA_ARG(ap, int32); + s_offset = _va_arg(ap, int32); if (!validate_app_str_addr(s_offset)) { return false; @@ -314,7 +318,7 @@ _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, out((int) (*s++), ctx); if (padding == PAD_SPACE_AFTER) { - int remaining = min_width - (s - start); + int remaining = min_width - (int32)(s - start); while (remaining-- > 0) { out(' ', ctx); } @@ -356,8 +360,8 @@ fail: struct str_context { char *str; - int max; - int count; + uint32 max; + uint32 count; }; static int @@ -371,7 +375,7 @@ sprintf_out(int c, struct str_context *ctx) if (ctx->count == ctx->max - 1) { ctx->str[ctx->count++] = '\0'; } else { - ctx->str[ctx->count++] = c; + ctx->str[ctx->count++] = (char)c; } return c; @@ -432,7 +436,7 @@ _printf_wrapper(wasm_module_inst_t module_inst, if (!_vprintf_wa((out_func_t)printf_out, &ctx, fmt, va_args, module_inst)) return 0; - return ctx.count; + return (int)ctx.count; } static int @@ -457,7 +461,7 @@ _sprintf_wrapper(wasm_module_inst_t module_inst, return 0; ctx.str = str; - ctx.max = app_end_offset - str_offset; + ctx.max = (uint32)(app_end_offset - str_offset); ctx.count = 0; if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, fmt, va_args, module_inst)) @@ -467,12 +471,12 @@ _sprintf_wrapper(wasm_module_inst_t module_inst, str[ctx.count] = '\0'; } - return ctx.count; + return (int)ctx.count; } static int _snprintf_wrapper(wasm_module_inst_t module_inst, - int32 str_offset, int32 size, int32 fmt_offset, + int32 str_offset, uint32 size, int32 fmt_offset, int32 va_list_offset) { struct str_context ctx; @@ -499,7 +503,7 @@ _snprintf_wrapper(wasm_module_inst_t module_inst, str[ctx.count] = '\0'; } - return ctx.count; + return (int)ctx.count; } static int @@ -536,21 +540,28 @@ _strdup_wrapper(wasm_module_inst_t module_inst, str = addr_app_to_native(str_offset); if (str) { - len = strlen(str) + 1; + len = (uint32)strlen(str) + 1; str_ret_offset = module_malloc(len); if (str_ret_offset) { str_ret = addr_app_to_native(str_ret_offset); - memcpy(str_ret, str, len); + bh_memcpy_s(str_ret, len, str, len); } } return str_ret_offset; } +static int32 +__strdup_wrapper(wasm_module_inst_t module_inst, + int32 str_offset) +{ + return _strdup_wrapper(module_inst, str_offset); +} + static int32 _memcmp_wrapper(wasm_module_inst_t module_inst, - int32 s1_offset, int32 s2_offset, int32 size) + int32 s1_offset, int32 s2_offset, uint32 size) { void *s1, *s2; @@ -565,7 +576,7 @@ _memcmp_wrapper(wasm_module_inst_t module_inst, static int32 _memcpy_wrapper(wasm_module_inst_t module_inst, - int32 dst_offset, int32 src_offset, int32 size) + int32 dst_offset, int32 src_offset, uint32 size) { void *dst, *src; @@ -578,13 +589,13 @@ _memcpy_wrapper(wasm_module_inst_t module_inst, dst = addr_app_to_native(dst_offset); src = addr_app_to_native(src_offset); - memcpy(dst, src, size); + bh_memcpy_s(dst, size, src, size); return dst_offset; } static int32 _memmove_wrapper(wasm_module_inst_t module_inst, - int32 dst_offset, int32 src_offset, int32 size) + int32 dst_offset, int32 src_offset, uint32 size) { void *dst, *src; @@ -600,7 +611,7 @@ _memmove_wrapper(wasm_module_inst_t module_inst, static int32 _memset_wrapper(wasm_module_inst_t module_inst, - int32 s_offset, int32 c, int32 size) + int32 s_offset, int32 c, uint32 size) { void *s; @@ -668,7 +679,7 @@ _strcpy_wrapper(wasm_module_inst_t module_inst, return 0; src = addr_app_to_native(src_offset); - len = strlen(src); + len = (uint32)strlen(src); if (!validate_app_addr(dst_offset, len + 1)) return 0; @@ -704,7 +715,7 @@ _strlen_wrapper(wasm_module_inst_t module_inst, return 0; s = addr_app_to_native(s_offset); - return strlen(s); + return (uint32)strlen(s); } static int32 @@ -719,13 +730,13 @@ _calloc_wrapper(wasm_module_inst_t module_inst, uint32 nmemb, uint32 size) { uint64 total_size = (uint64) nmemb * (uint64) size; - uint32 ret_offset = 0; + int32 ret_offset = 0; uint8 *ret_ptr; - if (total_size > UINT32_MAX) - total_size = UINT32_MAX; + if (total_size >= UINT32_MAX) + return 0; - ret_offset = module_malloc((uint32 )total_size); + ret_offset = module_malloc((uint32)total_size); if (ret_offset) { ret_ptr = addr_app_to_native(ret_offset); memset(ret_ptr, 0, (uint32) total_size); @@ -743,6 +754,245 @@ _free_wrapper(wasm_module_inst_t module_inst, return module_free(ptr_offset); } +static int32 +_atoi_wrapper(wasm_module_inst_t module_inst, + int32 s_offset) +{ + char *str; + + if (!validate_app_str_addr(s_offset)) + return 0; + + str = addr_app_to_native(s_offset); + + return atoi(str); +} + +static int32 +_bsearch_wrapper(wasm_module_inst_t module_inst, + int32 key_offset, /* const void * */ + int32 array_offset, /* const void * */ + uint32 count, + uint32 size, + int32 cmp_index) +{ + wasm_runtime_set_exception(module_inst, "bsearch not implemented."); + + return 0; +} + +static void +_exit_wrapper(wasm_module_inst_t module_inst, + int32 status) +{ + char buf[32]; + snprintf(buf, sizeof(buf), "env.exit(%i)", status); + wasm_runtime_set_exception(module_inst, buf); +} + +static int32 +_strtol_wrapper(wasm_module_inst_t module_inst, + int32 nptr_offset, /* const char * */ + int32 endptr_offset, /* char ** */ + int32 base) +{ + char *nptr, **endptr; + int32 num = 0; + + if (!validate_app_str_addr(nptr_offset) + || !validate_app_addr(endptr_offset, sizeof(int32))) + return 0; + + nptr = addr_app_to_native(nptr_offset); + endptr = addr_app_to_native(endptr_offset); + + num = (int32)strtol(nptr, endptr, base); + *(int32 *)endptr = addr_native_to_app(*endptr); + + return num; +} + +static uint32 +_strtoul_wrapper(wasm_module_inst_t module_inst, + int32 nptr_offset, /* const char * */ + int32 endptr_offset, /* char ** */ + int32 base) +{ + char *nptr, **endptr; + uint32 num = 0; + + if (!validate_app_str_addr(nptr_offset) + || !validate_app_addr(endptr_offset, sizeof(int32))) + return 0; + + nptr = addr_app_to_native(nptr_offset); + endptr = addr_app_to_native(endptr_offset); + + num = (uint32)strtoul(nptr, endptr, base); + *(int32 *)endptr = addr_native_to_app(*endptr); + + return num; +} + +static int32 +_memchr_wrapper(wasm_module_inst_t module_inst, + int32 s_offset, /* const void * */ + int32 c, + uint32 n) +{ + void *s, *res; + + if (!validate_app_addr(s_offset, n)) + return 0; + + s = (void*)addr_app_to_native(s_offset); + + res = memchr(s, c, n); + + return addr_native_to_app(res); +} + +static int32 +_strncasecmp_wrapper(wasm_module_inst_t module_inst, + int32 s1_offset, /* const char * */ + int32 s2_offset, /* const char * */ + uint32 n) +{ + char *s1, *s2; + + if (!validate_app_str_addr(s1_offset) + || !validate_app_str_addr(s2_offset)) + return 0; + + s1 = addr_app_to_native(s1_offset); + s2 = addr_app_to_native(s2_offset); + + return strncasecmp(s1, s2, n); +} + +static uint32 +_strspn_wrapper(wasm_module_inst_t module_inst, + int32 s_offset, /* const char * */ + int32 accept_offset) /* const char * */ +{ + char *s, *accept; + + if (!validate_app_str_addr(s_offset) + || !validate_app_str_addr(accept_offset)) + return 0; + + s = addr_app_to_native(s_offset); + accept = addr_app_to_native(accept_offset); + + return (uint32)strspn(s, accept); +} + +static uint32 +_strcspn_wrapper(wasm_module_inst_t module_inst, + int32 s_offset, /* const char * */ + int32 reject_offset) /* const char * */ +{ + char *s, *reject; + + if (!validate_app_str_addr(s_offset) + || !validate_app_str_addr(reject_offset)) + return 0; + + s = addr_app_to_native(s_offset); + reject = addr_app_to_native(reject_offset); + + return (uint32)strcspn(s, reject); +} + +static int32 +_strstr_wrapper(wasm_module_inst_t module_inst, + int32 s_offset, /* const char * */ + int32 find_offset) /* const char * */ +{ + char *s, *find, *res; + + if (!validate_app_str_addr(s_offset) + || !validate_app_str_addr(find_offset)) + return 0; + + s = addr_app_to_native(s_offset); + find = addr_app_to_native(find_offset); + + res = strstr(s, find); + + return addr_native_to_app(res); +} + +static int32 +_isupper_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isupper(c); +} + +static int32 +_isalpha_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isalpha(c); +} + +static int32 +_isspace_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isspace(c); +} + +static int32 +_isgraph_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isgraph(c); +} + +static int32 +_isprint_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isprint(c); +} + +static int32 +_isdigit_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isdigit(c); +} + +static int32 +_isxdigit_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isxdigit(c); +} + +static int32 +_tolower_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return tolower(c); +} + +static int32 +_toupper_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return toupper(c); +} + +static int32 +_isalnum_wrapper(wasm_module_inst_t module_inst, + int32 c) +{ + return isalnum(c); +} + static void setTempRet0_wrapper(wasm_module_inst_t module_inst, uint32 temp_ret) @@ -842,7 +1092,7 @@ _emscripten_memcpy_big_wrapper(wasm_module_inst_t module_inst, dst = addr_app_to_native(dst_offset); src = addr_app_to_native(src_offset); - memcpy(dst, src, size); + bh_memcpy_s(dst, size, src, size); return dst_offset; } @@ -873,6 +1123,36 @@ nullFunc_X_wrapper(wasm_module_inst_t module_inst, wasm_runtime_set_exception(module_inst, buf); } +static int32 +__cxa_allocate_exception_wrapper(wasm_module_inst_t module_inst, + uint32 thrown_size) +{ + int32 exception = module_malloc(thrown_size); + if (!exception) + return 0; + + return exception; +} + +static void +__cxa_begin_catch_wrapper(wasm_module_inst_t module_inst, + int32 exception_object_offset) +{ + +} + +static void +__cxa_throw_wrapper(wasm_module_inst_t module_inst, + int32 thrown_exception_offset, + int32 tinfo_offset, + uint32 table_elem_idx) +{ + char buf[32]; + + snprintf(buf, sizeof(buf), "%s", "exception thrown by stdc++"); + wasm_runtime_set_exception(module_inst, buf); +} + /*#define ENABLE_SPEC_TEST 1*/ #ifdef ENABLE_SPEC_TEST @@ -922,7 +1202,29 @@ static WASMNativeFuncDef native_func_defs[] = { REG_NATIVE_FUNC(env, _malloc), REG_NATIVE_FUNC(env, _calloc), REG_NATIVE_FUNC(env, _strdup), + /* clang may introduce __strdup */ + REG_NATIVE_FUNC(env, __strdup), REG_NATIVE_FUNC(env, _free), + REG_NATIVE_FUNC(env, _atoi), + REG_NATIVE_FUNC(env, _bsearch), + REG_NATIVE_FUNC(env, _exit), + REG_NATIVE_FUNC(env, _strtol), + REG_NATIVE_FUNC(env, _strtoul), + REG_NATIVE_FUNC(env, _memchr), + REG_NATIVE_FUNC(env, _strncasecmp), + REG_NATIVE_FUNC(env, _strspn), + REG_NATIVE_FUNC(env, _strcspn), + REG_NATIVE_FUNC(env, _strstr), + REG_NATIVE_FUNC(env, _isupper), + REG_NATIVE_FUNC(env, _isalpha), + REG_NATIVE_FUNC(env, _isspace), + REG_NATIVE_FUNC(env, _isgraph), + REG_NATIVE_FUNC(env, _isprint), + REG_NATIVE_FUNC(env, _isdigit), + REG_NATIVE_FUNC(env, _isxdigit), + REG_NATIVE_FUNC(env, _tolower), + REG_NATIVE_FUNC(env, _toupper), + REG_NATIVE_FUNC(env, _isalnum), REG_NATIVE_FUNC(env, setTempRet0), REG_NATIVE_FUNC(env, getTempRet0), REG_NATIVE_FUNC(env, _llvm_bswap_i16), @@ -934,7 +1236,10 @@ static WASMNativeFuncDef native_func_defs[] = { REG_NATIVE_FUNC(env, _emscripten_memcpy_big), REG_NATIVE_FUNC(env, abort), REG_NATIVE_FUNC(env, abortStackOverflow), - REG_NATIVE_FUNC(env, nullFunc_X) + REG_NATIVE_FUNC(env, nullFunc_X), + REG_NATIVE_FUNC(env, __cxa_allocate_exception), + REG_NATIVE_FUNC(env, __cxa_begin_catch), + REG_NATIVE_FUNC(env, __cxa_throw) }; void* @@ -960,6 +1265,11 @@ wasm_native_func_lookup(const char *module_name, const char *func_name) if ((ret = wasm_platform_native_func_lookup(module_name, func_name))) return ret; +#if WASM_ENABLE_WASI != 0 + if ((ret = wasi_native_func_lookup(module_name, func_name))) + return ret; +#endif + return NULL; } diff --git a/core/iwasm/lib/native/libc/wasi_wrapper.c b/core/iwasm/lib/native/libc/wasi_wrapper.c new file mode 100644 index 000000000..0bd447443 --- /dev/null +++ b/core/iwasm/lib/native/libc/wasi_wrapper.c @@ -0,0 +1,1289 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "wasm_native.h" +#include "wasm_export.h" +#include "wasm_log.h" +#include "wasm_platform_log.h" +#if WASM_ENABLE_WASI != 0 +#include "wasi_wrapper.h" +#endif +#include "bh_common.h" + +void +wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); + +#define get_wasi_ctx(module_inst) \ + wasm_runtime_get_wasi_ctx(module_inst) + +#define validate_app_addr(offset, size) \ + wasm_runtime_validate_app_addr(module_inst, offset, size) + +#define addr_app_to_native(offset) \ + wasm_runtime_addr_app_to_native(module_inst, offset) + +#define addr_native_to_app(ptr) \ + wasm_runtime_addr_native_to_app(module_inst, ptr) + +#define module_malloc(size) \ + wasm_runtime_module_malloc(module_inst, size) + +#define module_free(offset) \ + wasm_runtime_module_free(module_inst, offset) + +#if WASM_ENABLE_WASI != 0 + +#define WASI_CHECK_ERR() do { \ + if (err) { \ + return err; \ + } \ + } while (0) + +typedef struct wasi_prestat_app { + wasi_preopentype_t pr_type; + uint32 pr_name_len; +} wasi_prestat_app_t; + +typedef struct iovec_app { + int32 buf_offset; + uint32 buf_len; +} iovec_app_t; + +typedef struct WASIContext { + void *curfds; + void *prestats; + void *argv_environ; +} *wasi_ctx_t; + +wasi_ctx_t +wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst); + +static wasi_errno_t +wasi_args_get(wasm_module_inst_t module_inst, + int32 argv_offset /* char ** */, + int32 argv_buf_offset /* char * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + size_t argc, argv_buf_size, i; + uint64 total_size1, total_size2; + int32 *argv_app; + char *argv_buf_app; + wasi_errno_t err; + char **argv; + + err = wasmtime_ssp_args_sizes_get(wasi_ctx->argv_environ, + &argc, &argv_buf_size); + WASI_CHECK_ERR(); + + total_size1 = sizeof(char *) * ((uint64)argc + 1); + total_size2 = sizeof(char) * (uint64)argv_buf_size; + if (total_size1 >= UINT32_MAX + || !validate_app_addr(argv_offset, (uint32)total_size1) + || total_size2 >= UINT32_MAX + || !validate_app_addr(argv_buf_offset, (uint32)total_size2)) + return (wasi_errno_t)-1; + + argv = bh_malloc((uint32)total_size1); + if (!argv) + return (wasi_errno_t)-1; + + argv_app = (int32*)addr_app_to_native(argv_offset); + argv_buf_app= (char*)addr_app_to_native(argv_buf_offset); + + err = wasmtime_ssp_args_get(wasi_ctx->argv_environ, + argv, argv_buf_app); + if (err) + goto fail; + + for (i = 0; i < argc; i++) + argv_app[i] = addr_native_to_app(argv[i]); + argv_app[argc] = 0; + + /* success */ + err = 0; + +fail: + bh_free(argv); + return err; +} + +static wasi_errno_t +wasi_args_sizes_get(wasm_module_inst_t module_inst, + int32 argc_offset /* size_t * */, + int32 argv_buf_size_offset /* size_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + size_t argc, argv_buf_size; + uint32 *argc_app, *argv_buf_size_app; + wasi_errno_t err; + + if (!validate_app_addr(argc_offset, sizeof(uint32)) + || !validate_app_addr(argv_buf_size_offset, sizeof(uint32))) + return (wasi_errno_t)-1; + + argc_app = (uint32*)addr_app_to_native(argc_offset); + argv_buf_size_app = (uint32*)addr_app_to_native(argv_buf_size_offset); + + err = wasmtime_ssp_args_sizes_get(wasi_ctx->argv_environ, + &argc, &argv_buf_size); + WASI_CHECK_ERR(); + + *(uint32*)argc_app = (uint32)argc; + *(uint32*)argv_buf_size_app = (uint32)argv_buf_size; + + return 0; +} + +static wasi_errno_t +wasi_clock_res_get(wasm_module_inst_t module_inst, + wasi_clockid_t clock_id, + int32 resolution_offset /* wasi_timestamp_t * */) +{ + wasi_timestamp_t resolution; + uint32 *resolution_app; + wasi_errno_t err; + + if (!validate_app_addr(resolution_offset, sizeof(wasi_timestamp_t))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_clock_res_get(clock_id, &resolution); + WASI_CHECK_ERR(); + + resolution_app = addr_app_to_native(resolution_offset); + + memcpy(resolution_app, &resolution, sizeof(wasi_timestamp_t)); + + return 0; +} + +static wasi_errno_t +wasi_clock_time_get(wasm_module_inst_t module_inst, + wasi_clockid_t clock_id, + wasi_timestamp_t precision, + int32 time_offset /*wasi_timestamp_t * */) +{ + wasi_timestamp_t time; + uint32 *time_app; + wasi_errno_t err; + + if (!validate_app_addr(time_offset, sizeof(wasi_timestamp_t))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_clock_time_get(clock_id, precision, &time); + WASI_CHECK_ERR(); + + time_app = addr_app_to_native(time_offset); + + memcpy(time_app, &time, sizeof(wasi_timestamp_t)); + + return 0; +} + +static wasi_errno_t +wasi_environ_get(wasm_module_inst_t module_inst, + int32 environ_offset /* char ** */, + int32 environ_buf_offset /* char */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + size_t environ_count, environ_buf_size, i; + uint64 total_size; + int32 *environ_app; + char *environ_buff_app; + char **environ; + wasi_errno_t err; + + err = wasmtime_ssp_environ_sizes_get(wasi_ctx->argv_environ, + &environ_count, &environ_buf_size); + WASI_CHECK_ERR(); + + total_size = sizeof(uint32) * ((uint64)environ_count + 1); + if (total_size >= UINT32_MAX + || !validate_app_addr(environ_offset, (uint32)total_size) + || environ_buf_size >= UINT32_MAX + || !validate_app_addr(environ_buf_offset, (uint32)environ_buf_size)) + return (wasi_errno_t)-1; + + environ_app = (int32*)addr_app_to_native(environ_offset); + environ_buff_app = (char*)addr_app_to_native(environ_buf_offset); + + environ = bh_malloc((uint32)total_size); + if (!environ) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_environ_get(wasi_ctx->argv_environ, + environ, environ_buff_app); + if (err) + goto fail; + + for (i = 0; i < environ_count; i++) + environ_app[i] = addr_native_to_app(environ[i]); + environ_app[environ_count] = 0; + + /* success */ + err = 0; + +fail: + bh_free(environ); + return err; +} + +static wasi_errno_t +wasi_environ_sizes_get(wasm_module_inst_t module_inst, + int32 environ_count_offset /* size_t * */, + int32 environ_buf_size_offset /* size_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + size_t environ_count, environ_buf_size; + uint32 *environ_count_app, *environ_buf_size_app; + wasi_errno_t err; + + if (!validate_app_addr(environ_count_offset, sizeof(uint32)) + || !validate_app_addr(environ_buf_size_offset, sizeof(uint32))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_environ_sizes_get(wasi_ctx->argv_environ, + &environ_count, &environ_buf_size); + WASI_CHECK_ERR(); + + environ_count_app = (uint32*)addr_app_to_native(environ_count_offset); + environ_buf_size_app = (uint32*)addr_app_to_native(environ_buf_size_offset); + + *(uint32*)environ_count_app = (uint32)environ_count; + *(uint32*)environ_buf_size_app = (uint32)environ_buf_size; + + return 0; +} + +static wasi_errno_t +wasi_fd_prestat_get(wasm_module_inst_t module_inst, + wasi_fd_t fd, + int32 buf_offset /* wasi_prestat_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + wasi_prestat_app_t *prestat_app; + wasi_prestat_t prestat; + wasi_errno_t err; + + if (!validate_app_addr(buf_offset, sizeof(wasi_prestat_app_t))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_fd_prestat_get(wasi_ctx->prestats, fd, &prestat); + WASI_CHECK_ERR(); + + prestat_app = (wasi_prestat_app_t*)addr_app_to_native(buf_offset); + prestat_app->pr_type = prestat.pr_type; + prestat_app->pr_name_len = (uint32)prestat.u.dir.pr_name_len; + + return 0; +} + +static wasi_errno_t +wasi_fd_prestat_dir_name(wasm_module_inst_t module_inst, + wasi_fd_t fd, + int32 path_offset /* char * */, + uint32 path_len) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + char *path_app; + + if (!validate_app_addr(path_offset, path_len)) + return (wasi_errno_t)-1; + + path_app = (char*)addr_app_to_native(path_offset); + return wasmtime_ssp_fd_prestat_dir_name(wasi_ctx->prestats, fd, + path_app, path_len); +} + +static wasi_errno_t +wasi_fd_close(wasm_module_inst_t module_inst, wasi_fd_t fd) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + + return wasmtime_ssp_fd_close(wasi_ctx->curfds, wasi_ctx->prestats, fd); +} + +static wasi_errno_t +wasi_fd_datasync(wasm_module_inst_t module_inst, wasi_fd_t fd) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + + return wasmtime_ssp_fd_datasync(wasi_ctx->curfds, fd); +} + +static wasi_errno_t +wasi_fd_pread(wasm_module_inst_t module_inst, + wasi_fd_t fd, + int32 iovs_offset /* const wasi_iovec_t * */, + uint32 iovs_len, + wasi_filesize_t offset, + int32 nread_offset /* size_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + int32 mem; + wasi_iovec_t *iovec, *iovec_begin; + iovec_app_t *iovec_app; + uint32 i; + size_t nread; + uint32 *nread_app; + uint64 total_size; + wasi_errno_t err; + + total_size = sizeof(iovec_app_t) * (uint64)iovs_len; + if (!validate_app_addr(nread_offset, (uint32)sizeof(uint32)) + || total_size >= UINT32_MAX + || !validate_app_addr(iovs_offset, (uint32)total_size)) + return (wasi_errno_t)-1; + + iovec_app = (iovec_app_t*)addr_app_to_native(iovs_offset); + if (!iovec_app) + return (wasi_errno_t)-1; + + total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len; + if (total_size >= UINT32_MAX + || !(mem = module_malloc((uint32)total_size))) + return (wasi_errno_t)-1; + + iovec = iovec_begin = (wasi_iovec_t*)addr_app_to_native(mem); + + for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) { + if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { + err = (wasi_errno_t)-1; + goto fail; + } + iovec->buf = (void*)addr_app_to_native(iovec_app->buf_offset); + iovec->buf_len = iovec_app->buf_len; + } + + err = wasmtime_ssp_fd_pread(wasi_ctx->curfds, fd, iovec_begin, + iovs_len, offset, &nread); + if (err) + goto fail; + + nread_app = (uint32*)addr_app_to_native(nread_offset); + *(uint32*)nread_app = (uint32)nread; + + /* success */ + err = 0; + +fail: + module_free(mem); + return err; +} + +static wasi_errno_t +wasi_fd_pwrite(wasm_module_inst_t module_inst, + wasi_fd_t fd, + int32 iovs_offset /* const wasi_ciovec_t * */, + uint32 iovs_len, + wasi_filesize_t offset, + int32 nwritten_offset /* size_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + int32 mem; + wasi_ciovec_t *ciovec, *ciovec_begin; + iovec_app_t *ciovec_app; + uint32 i; + size_t nwritten; + uint32 *nwritten_app; + uint64 total_size; + wasi_errno_t err; + + total_size = sizeof(iovec_app_t) * (uint64)iovs_len; + if (!validate_app_addr(nwritten_offset, (uint32)sizeof(uint32)) + || total_size >= UINT32_MAX + || !validate_app_addr(iovs_offset, (uint32)total_size)) + return (wasi_errno_t)-1; + + ciovec_app = (iovec_app_t*)addr_app_to_native(iovs_offset); + + total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len; + if (total_size >= UINT32_MAX + || !(mem = module_malloc((uint32)total_size))) + return (wasi_errno_t)-1; + + ciovec_begin = ciovec = (wasi_ciovec_t*)addr_app_to_native(mem); + for (i = 0; i < iovs_len; i++, ciovec_app++, ciovec++) { + if (!validate_app_addr(ciovec_app->buf_offset, ciovec_app->buf_len)) { + err = (wasi_errno_t)-1; + goto fail; + } + ciovec->buf = (char*)addr_app_to_native(ciovec_app->buf_offset); + ciovec->buf_len = ciovec_app->buf_len; + } + + err = wasmtime_ssp_fd_pwrite(wasi_ctx->curfds, fd, ciovec_begin, + iovs_len, offset, &nwritten); + if (err) + goto fail; + + nwritten_app = (uint32*)addr_app_to_native(nwritten_offset); + *(uint32*)nwritten_app = (uint32)nwritten; + + /* success */ + err = 0; + +fail: + module_free(mem); + return err; +} + +static wasi_errno_t +wasi_fd_read(wasm_module_inst_t module_inst, + wasi_fd_t fd, + int32 iovs_offset /* const wasi_iovec_t * */, + uint32 iovs_len, + int32 nread_offset /* size_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + int32 mem; + wasi_iovec_t *iovec, *iovec_begin; + iovec_app_t *iovec_app; + uint32 i; + size_t nread; + uint32 *nread_app; + uint64 total_size; + wasi_errno_t err; + + total_size = sizeof(iovec_app_t) * (uint64)iovs_len; + if (!validate_app_addr(nread_offset, (uint32)sizeof(uint32)) + || total_size >= UINT32_MAX + || !validate_app_addr(iovs_offset, (uint32)total_size)) + return (wasi_errno_t)-1; + + iovec_app = (iovec_app_t*)addr_app_to_native(iovs_offset); + + total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len; + if (total_size >= UINT32_MAX + || !(mem = module_malloc((uint32)total_size))) + return (wasi_errno_t)-1; + + iovec = iovec_begin = (wasi_iovec_t*)addr_app_to_native(mem); + + for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) { + if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) { + err = (wasi_errno_t)-1; + goto fail; + } + iovec->buf = (void*)addr_app_to_native(iovec_app->buf_offset); + iovec->buf_len = iovec_app->buf_len; + } + + err = wasmtime_ssp_fd_read(wasi_ctx->curfds, fd, + iovec_begin, iovs_len, &nread); + if (err) + goto fail; + + nread_app = (uint32*)addr_app_to_native(nread_offset); + *(uint32*)nread_app = (uint32)nread; + + /* success */ + err = 0; + +fail: + module_free(mem); + return err; +} + +static wasi_errno_t +wasi_fd_renumber(wasm_module_inst_t module_inst, + wasi_fd_t from, wasi_fd_t to) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + + return wasmtime_ssp_fd_renumber(wasi_ctx->curfds, + wasi_ctx->prestats, from, to); +} + +static wasi_errno_t +wasi_fd_seek(wasm_module_inst_t module_inst, + wasi_fd_t fd, + wasi_filedelta_t offset, + wasi_whence_t whence, + int32 newoffset_offset /* wasi_filesize_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + size_t newoffset; + uint64 *newoffset_app; + wasi_errno_t err; + + if (!validate_app_addr(newoffset_offset, sizeof(uint64))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_fd_seek(wasi_ctx->curfds, fd, + offset, whence, &newoffset); + WASI_CHECK_ERR(); + + newoffset_app = (uint64*)addr_app_to_native(newoffset_offset); + *(uint64*)newoffset_app = (uint64)newoffset; + + return 0; +} + +static wasi_errno_t +wasi_fd_tell(wasm_module_inst_t module_inst, + wasi_fd_t fd, + int32 newoffset_offset /* wasi_filesize_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + size_t newoffset; + uint64 *newoffset_app; + wasi_errno_t err; + + if (!validate_app_addr(newoffset_offset, sizeof(uint64))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_fd_tell(wasi_ctx->curfds, fd, &newoffset); + WASI_CHECK_ERR(); + + newoffset_app = (uint64*)addr_app_to_native(newoffset_offset); + *(uint64*)newoffset_app = (uint64)newoffset; + + return 0; +} + +static wasi_errno_t +wasi_fd_fdstat_get(wasm_module_inst_t module_inst, + wasi_fd_t fd, + int32 buf_offset /* wasi_fdstat_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + wasi_fdstat_t fdstat, *fdstat_app; + wasi_errno_t err; + + if (!validate_app_addr(buf_offset, sizeof(wasi_fdstat_t))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_fd_fdstat_get(wasi_ctx->curfds, fd, &fdstat); + WASI_CHECK_ERR(); + + fdstat_app = (wasi_fdstat_t*)addr_app_to_native(buf_offset); + memcpy(fdstat_app, &fdstat, sizeof(wasi_fdstat_t)); + + return 0; +} + +static wasi_errno_t +wasi_fd_fdstat_set_flags(wasm_module_inst_t module_inst, + wasi_fd_t fd, + wasi_fdflags_t flags) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + + return wasmtime_ssp_fd_fdstat_set_flags(wasi_ctx->curfds, fd, flags); + +} + +static wasi_errno_t +wasi_fd_fdstat_set_rights(wasm_module_inst_t module_inst, + wasi_fd_t fd, + wasi_rights_t fs_rights_base, + wasi_rights_t fs_rights_inheriting) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + + return wasmtime_ssp_fd_fdstat_set_rights(wasi_ctx->curfds, fd, + fs_rights_base, fs_rights_inheriting); +} + +static wasi_errno_t +wasi_fd_sync(wasm_module_inst_t module_inst, wasi_fd_t fd) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + + return wasmtime_ssp_fd_sync(wasi_ctx->curfds, fd); +} + +static wasi_errno_t +wasi_fd_write(wasm_module_inst_t module_inst, + wasi_fd_t fd, + int32 iovs_offset /* const wasi_ciovec_t * */, + uint32 iovs_len, + int32 nwritten_offset /* size_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + int32 mem; + wasi_ciovec_t *ciovec, *ciovec_begin; + iovec_app_t *ciovec_app; + uint32 i; + size_t nwritten; + uint32 *nwritten_app; + uint64 total_size; + wasi_errno_t err; + + total_size = sizeof(iovec_app_t) * (uint64)iovs_len; + if (!validate_app_addr(nwritten_offset, (uint32)sizeof(uint32)) + || total_size >= UINT32_MAX + || !validate_app_addr(iovs_offset, (uint32)total_size)) + return (wasi_errno_t)-1; + + ciovec_app = (iovec_app_t*)addr_app_to_native(iovs_offset); + + total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len; + if (total_size >= UINT32_MAX + || !(mem = module_malloc((uint32)total_size))) + return (wasi_errno_t)-1; + + ciovec_begin = ciovec = (wasi_ciovec_t*)addr_app_to_native(mem); + for (i = 0; i < iovs_len; i++, ciovec_app++, ciovec++) { + if (!validate_app_addr(ciovec_app->buf_offset, ciovec_app->buf_len)) { + err = (wasi_errno_t)-1; + goto fail; + } + ciovec->buf = (char*)addr_app_to_native(ciovec_app->buf_offset); + ciovec->buf_len = ciovec_app->buf_len; + } + + err = wasmtime_ssp_fd_write(wasi_ctx->curfds, fd, + ciovec_begin, iovs_len, &nwritten); + if (err) + goto fail; + + nwritten_app = (uint32*)addr_app_to_native(nwritten_offset); + *(uint32*)nwritten_app = (uint32)nwritten; + + /* success */ + err = 0; + +fail: + module_free(mem); + return err; +} + +static wasi_errno_t +wasi_fd_advise(wasm_module_inst_t module_inst, + wasi_fd_t fd, + wasi_filesize_t offset, + wasi_filesize_t len, + wasi_advice_t advice) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + + return wasmtime_ssp_fd_advise(wasi_ctx->curfds, fd, offset, len, advice); +} + +static wasi_errno_t +wasi_fd_allocate(wasm_module_inst_t module_inst, + wasi_fd_t fd, + wasi_filesize_t offset, + wasi_filesize_t len) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + + return wasmtime_ssp_fd_allocate(wasi_ctx->curfds, fd, offset, len); +} + +static wasi_errno_t +wasi_path_create_directory(wasm_module_inst_t module_inst, + wasi_fd_t fd, + int32 path_offset /* const char * */, + uint32 path_len) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + char *path; + + if (!validate_app_addr(path_offset, path_len)) + return (wasi_errno_t)-1; + + path = (char*)addr_app_to_native(path_offset); + + return wasmtime_ssp_path_create_directory(wasi_ctx->curfds, fd, + path, path_len); +} + +static wasi_errno_t +wasi_path_link(wasm_module_inst_t module_inst, + wasi_fd_t old_fd, + wasi_lookupflags_t old_flags, + int32 old_path_offset /* const char * */, + uint32 old_path_len, + wasi_fd_t new_fd, + int32 new_path_offset /* const char * */, + uint32 new_path_len) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + char *old_path, *new_path; + + if (!validate_app_addr(old_path_offset, old_path_len) + || !validate_app_addr(new_path_offset, new_path_len)) + return (wasi_errno_t)-1; + + old_path = (char*)addr_app_to_native(old_path_offset); + new_path = (char*)addr_app_to_native(new_path_offset); + + return wasmtime_ssp_path_link(wasi_ctx->curfds, old_fd, + old_flags, old_path, old_path_len, + new_fd, new_path, new_path_len); +} + +static wasi_errno_t +wasi_path_open(wasm_module_inst_t module_inst, + wasi_fd_t dirfd, + wasi_lookupflags_t dirflags, + int32 path_offset /* const char * */, + uint32 path_len, + wasi_oflags_t oflags, + wasi_rights_t fs_rights_base, + wasi_rights_t fs_rights_inheriting, + wasi_fdflags_t fs_flags, + int32 fd_offset /* wasi_fd_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + char *path; + wasi_fd_t fd = (wasi_fd_t)-1; + uint32 *fd_app; + wasi_errno_t err; + + if (!validate_app_addr(path_offset, path_len) + || !validate_app_addr(fd_offset, 1)) + return (wasi_errno_t)-1; + + path = (char*)addr_app_to_native(path_offset); + + err = wasmtime_ssp_path_open(wasi_ctx->curfds, + dirfd, dirflags, + path, path_len, + oflags, + fs_rights_base, + fs_rights_inheriting, + fs_flags, + &fd); + + fd_app = (wasi_fd_t*)addr_app_to_native(fd_offset); + *fd_app = (uint32)fd; + + WASI_CHECK_ERR(); + + return 0; +} + +static wasi_errno_t +wasi_fd_readdir(wasm_module_inst_t module_inst, + wasi_fd_t fd, + int32 buf_offset /* void *buf */, + uint32 buf_len, + wasi_dircookie_t cookie, + int32 bufused_offset /* size_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + void *buf; + size_t bufused; + uint32 *bufused_app; + wasi_errno_t err; + + if (!validate_app_addr(buf_offset, buf_len) + || !validate_app_addr(bufused_offset, sizeof(uint32))) + return (wasi_errno_t)-1; + + buf = (void*)addr_app_to_native(buf_offset); + + err = wasmtime_ssp_fd_readdir(wasi_ctx->curfds, fd, + buf, buf_len, cookie, &bufused); + WASI_CHECK_ERR(); + + bufused_app = (uint32*)addr_app_to_native(bufused_offset); + *(uint32*)bufused_app = (uint32)bufused; + + return 0; +} + +static wasi_errno_t +wasi_path_readlink(wasm_module_inst_t module_inst, + wasi_fd_t fd, + int32 path_offset /* const char * */, + uint32 path_len, + int32 buf_offset /* char * */, + uint32 buf_len, + int32 bufused_offset /* size_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + char *path, *buf; + size_t bufused; + uint32 *bufused_app; + wasi_errno_t err; + + if (!validate_app_addr(path_offset, path_len) + || !validate_app_addr(buf_offset, buf_len) + || !validate_app_addr(bufused_offset, sizeof(uint32))) + return (wasi_errno_t)-1; + + path = (char*)addr_app_to_native(path_offset); + buf = (char*)addr_app_to_native(buf_offset); + + err = wasmtime_ssp_path_readlink(wasi_ctx->curfds, fd, + path, path_len, buf, + buf_len, &bufused); + WASI_CHECK_ERR(); + + bufused_app = (uint32*)addr_app_to_native(bufused_offset); + *(uint32*)bufused_app = (uint32)bufused; + + return 0; +} + +static wasi_errno_t +wasi_path_rename(wasm_module_inst_t module_inst, + wasi_fd_t old_fd, + int32 old_path_offset /* const char * */, + uint32 old_path_len, + wasi_fd_t new_fd, + int32 new_path_offset /* const char * */, + uint32 new_path_len) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + char *old_path, *new_path; + + if (!validate_app_addr(old_path_offset, old_path_len) + || !validate_app_addr(new_path_offset, new_path_len)) + return (wasi_errno_t)-1; + + old_path = (char*)addr_app_to_native(old_path_offset); + new_path = (char*)addr_app_to_native(new_path_offset); + + return wasmtime_ssp_path_rename(wasi_ctx->curfds, old_fd, + old_path, old_path_len, + new_fd, new_path, + new_path_len); +} + +static wasi_errno_t +wasi_fd_filestat_get(wasm_module_inst_t module_inst, + wasi_fd_t fd, + int32 buf_offset /* wasi_filestat_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + wasi_filestat_t filestat, *filestat_app; + wasi_errno_t err; + + if (!validate_app_addr(buf_offset, sizeof(wasi_filestat_t))) + return (wasi_errno_t)-1; + + err = wasmtime_ssp_fd_filestat_get(wasi_ctx->curfds, fd, &filestat); + WASI_CHECK_ERR(); + + filestat_app = (wasi_filestat_t*)addr_app_to_native(buf_offset); + memcpy(filestat_app, &filestat, sizeof(wasi_filestat_t)); + + return 0; +} + +static wasi_errno_t +wasi_fd_filestat_set_times(wasm_module_inst_t module_inst, + wasi_fd_t fd, + wasi_timestamp_t st_atim, + wasi_timestamp_t st_mtim, + wasi_fstflags_t fstflags) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + + return wasmtime_ssp_fd_filestat_set_times(wasi_ctx->curfds, fd, + st_atim, st_mtim, fstflags); +} + +static wasi_errno_t +wasi_fd_filestat_set_size(wasm_module_inst_t module_inst, + wasi_fd_t fd, + wasi_filesize_t st_size) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + + return wasmtime_ssp_fd_filestat_set_size(wasi_ctx->curfds, fd, st_size); +} + +static wasi_errno_t +wasi_path_filestat_get(wasm_module_inst_t module_inst, + wasi_fd_t fd, + wasi_lookupflags_t flags, + int32 path_offset /* const char * */, + uint32 path_len, + int32 buf_offset /* wasi_filestat_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + char *path; + wasi_filestat_t filestat, *filestat_app; + wasi_errno_t err; + + if (!validate_app_addr(path_offset, path_len) + || !validate_app_addr(buf_offset, sizeof(wasi_filestat_t))) + return (wasi_errno_t)-1; + + path = (char*)addr_app_to_native(path_offset); + + err = wasmtime_ssp_path_filestat_get(wasi_ctx->curfds, fd, + flags, path, path_len, &filestat); + WASI_CHECK_ERR(); + + filestat_app = (wasi_filestat_t*)addr_app_to_native(buf_offset); + memcpy(filestat_app, &filestat, sizeof(wasi_filestat_t)); + + return 0; +} + +static wasi_errno_t +wasi_path_filestat_set_times(wasm_module_inst_t module_inst, + wasi_fd_t fd, + wasi_lookupflags_t flags, + int32 path_offset /* const char * */, + uint32 path_len, + wasi_timestamp_t st_atim, + wasi_timestamp_t st_mtim, + wasi_fstflags_t fstflags) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + char *path; + + if (!validate_app_addr(path_offset, path_len)) + return (wasi_errno_t)-1; + + path = (char*)addr_app_to_native(path_offset); + + return wasmtime_ssp_path_filestat_set_times(wasi_ctx->curfds, fd, + flags, path, path_len, + st_atim, st_mtim, fstflags); +} + +static wasi_errno_t +wasi_path_symlink(wasm_module_inst_t module_inst, + int32 old_path_offset /* const char * */, + uint32 old_path_len, + wasi_fd_t fd, + int32 new_path_offset /* const char * */, + uint32 new_path_len) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + char *old_path, *new_path; + + if (!validate_app_addr(old_path_offset, old_path_len) + || !validate_app_addr(new_path_offset, new_path_len)) + return (wasi_errno_t)-1; + + old_path = (char*)addr_app_to_native(old_path_offset); + new_path = (char*)addr_app_to_native(new_path_offset); + + return wasmtime_ssp_path_symlink(wasi_ctx->curfds, old_path, + old_path_len, fd, new_path, + new_path_len); +} + +static wasi_errno_t +wasi_path_unlink_file(wasm_module_inst_t module_inst, + wasi_fd_t fd, + int32 path_offset /* const char * */, + uint32 path_len) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + char *path; + + if (!validate_app_addr(path_offset, path_len)) + return (wasi_errno_t)-1; + + path = (char*)addr_app_to_native(path_offset); + + return wasmtime_ssp_path_unlink_file(wasi_ctx->curfds, fd, path, path_len); +} + +static wasi_errno_t +wasi_path_remove_directory(wasm_module_inst_t module_inst, + wasi_fd_t fd, + int32 path_offset /* const char * */, + uint32 path_len) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + char *path; + + if (!validate_app_addr(path_offset, path_len)) + return (wasi_errno_t)-1; + + path = (char*)addr_app_to_native(path_offset); + + return wasmtime_ssp_path_remove_directory(wasi_ctx->curfds, fd, path, path_len); +} + +static wasi_errno_t +wasi_poll_oneoff(wasm_module_inst_t module_inst, + int32 in_offset /* const wasi_subscription_t * */, + int32 out_offset /* wasi_event_t * */, + uint32 nsubscriptions, + int32 nevents_offset /* size_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + wasi_subscription_t *in; + wasi_event_t *out; + size_t nevents; + uint32 *nevents_app; + wasi_errno_t err; + + if (!validate_app_addr(in_offset, sizeof(wasi_subscription_t)) + || !validate_app_addr(out_offset, sizeof(wasi_event_t)) + || !validate_app_addr(nevents_offset, sizeof(uint32))) + return (wasi_errno_t)-1; + + in = (wasi_subscription_t*)addr_app_to_native(in_offset); + out = (wasi_event_t*)addr_app_to_native(out_offset); + + err = wasmtime_ssp_poll_oneoff(wasi_ctx->curfds, in, out, nsubscriptions, &nevents); + WASI_CHECK_ERR(); + + nevents_app = (uint32*)addr_app_to_native(nevents_offset); + *(uint32*)nevents_app = (uint32)nevents; + + return 0; +} + +void wasi_proc_exit(wasm_module_inst_t module_inst, + wasi_exitcode_t rval) +{ + wasm_runtime_set_exception(module_inst, "wasi proc exit"); +} + +static wasi_errno_t +wasi_proc_raise(wasm_module_inst_t module_inst, + wasi_signal_t sig) +{ + char buf[32]; + snprintf(buf, sizeof(buf), "%s%d", "wasi proc raise ", sig); + wasm_runtime_set_exception(module_inst, buf); + + return 0; +} + +static wasi_errno_t +wasi_random_get(wasm_module_inst_t module_inst, + int32 buf_offset /* void * */, + uint32 buf_len) +{ + void *buf; + + if (!validate_app_addr(buf_offset, buf_len)) + return (wasi_errno_t)-1; + + buf = (void*)addr_app_to_native(buf_offset); + + return wasmtime_ssp_random_get(buf, buf_len); +} + +static wasi_errno_t +wasi_sock_recv(wasm_module_inst_t module_inst, + wasi_fd_t sock, + int32 ri_data_offset /* const wasi_iovec_t * */, + uint32 ri_data_len, + wasi_riflags_t ri_flags, + int32 ro_datalen_offset /* size_t * */, + int32 ro_flags_offset /* wasi_roflags_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + wasi_iovec_t *iovec, *iovec_begin; + int32 mem; + iovec_app_t *ri_data_app; + uint32 i; + size_t ro_datalen; + wasi_roflags_t ro_flags; + uint32 *ro_datalen_app, *ro_flags_app; + uint64 total_size; + wasi_errno_t err; + + total_size = sizeof(iovec_app_t) * (uint64)ri_data_len; + if (!validate_app_addr(ro_datalen_offset, (uint32)sizeof(uint32)) + || !validate_app_addr(ro_flags_offset, (uint32)sizeof(uint32)) + || total_size >= UINT32_MAX + || !validate_app_addr(ri_data_offset, (uint32)total_size)) + return (wasi_errno_t)-1; + + ri_data_app = (iovec_app_t*)addr_app_to_native(ri_data_offset); + + total_size = sizeof(wasi_iovec_t) * (uint64)ri_data_len; + if (total_size >= UINT32_MAX + || !(mem = module_malloc((uint32)total_size))) + return (wasi_errno_t)-1; + + iovec = iovec_begin = (wasi_iovec_t*)addr_app_to_native(mem); + + for (i = 0; i < ri_data_len; i++, ri_data_app++, iovec++) { + if (!validate_app_addr(ri_data_app->buf_offset, ri_data_app->buf_len)) { + err = (wasi_errno_t)-1; + goto fail; + } + iovec->buf = (void*)addr_app_to_native(ri_data_app->buf_offset); + iovec->buf_len = ri_data_app->buf_len; + } + + err = wasmtime_ssp_sock_recv(wasi_ctx->curfds, sock, + iovec_begin, ri_data_len, + ri_flags, &ro_datalen, + &ro_flags); + if (err) + goto fail; + + ro_datalen_app = (uint32*)addr_app_to_native(ro_datalen_offset); + ro_flags_app = (uint32*)addr_app_to_native(ro_flags_offset); + + *(uint32*)ro_datalen_app = (uint32)ro_datalen; + *(uint32*)ro_flags_app = (uint32)ro_flags; + + /* success */ + err = 0; + +fail: + module_free(mem); + return err; +} + +static wasi_errno_t +wasi_sock_send(wasm_module_inst_t module_inst, + wasi_fd_t sock, + int32 si_data_offset /* const wasi_ciovec_t * */, + uint32 si_data_len, + wasi_siflags_t si_flags, + int32 so_datalen_offset /* size_t * */) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + int32 mem; + wasi_ciovec_t *ciovec, *ciovec_begin; + iovec_app_t *si_data_app; + uint32 i; + size_t so_datalen; + uint32 *so_datalen_app; + uint64 total_size; + wasi_errno_t err; + + total_size = sizeof(iovec_app_t) * (uint64)si_data_len; + if (!validate_app_addr(so_datalen_offset, sizeof(uint32)) + || total_size >= UINT32_MAX + || !validate_app_addr(si_data_offset, (uint32)total_size)) + return (wasi_errno_t)-1; + + si_data_app = (iovec_app_t*)addr_app_to_native(si_data_offset); + + total_size = sizeof(wasi_ciovec_t) * (uint64)si_data_len; + if (total_size >= UINT32_MAX + || !(mem = module_malloc((uint32)total_size))) + return (wasi_errno_t)-1; + + ciovec_begin = ciovec = (wasi_ciovec_t*)addr_app_to_native(mem); + + for (i = 0; i < si_data_len; i++, si_data_app++, ciovec++) { + if (!validate_app_addr(si_data_app->buf_offset, si_data_app->buf_len)) { + err = (wasi_errno_t)-1; + goto fail; + } + ciovec->buf = (char*)addr_app_to_native(si_data_app->buf_offset); + ciovec->buf_len = si_data_app->buf_len; + } + + err = wasmtime_ssp_sock_send(wasi_ctx->curfds, sock, + ciovec_begin, si_data_len, + si_flags, &so_datalen); + if (err) + goto fail; + + so_datalen_app = (uint32*)addr_app_to_native(so_datalen_offset); + *(uint32*)so_datalen_app = (uint32)so_datalen; + + /* success */ + err = 0; + +fail: + module_free(mem); + return err; +} + +static wasi_errno_t +wasi_sock_shutdown(wasm_module_inst_t module_inst, + wasi_fd_t sock, wasi_sdflags_t how) +{ + wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); + + return wasmtime_ssp_sock_shutdown(wasi_ctx->curfds, sock, how); +} + +static wasi_errno_t +wasi_sched_yield(wasm_module_inst_t module_inst) +{ + return wasmtime_ssp_sched_yield(); +} + +#define REG_NATIVE_FUNC(func_name) \ + { "wasi_unstable", #func_name, wasi_##func_name } + +typedef struct WASMNativeFuncDef { + const char *module_name; + const char *func_name; + void *func_ptr; +} WASMNativeFuncDef; + +static WASMNativeFuncDef native_func_defs[] = { + REG_NATIVE_FUNC(args_get), + REG_NATIVE_FUNC(args_sizes_get), + REG_NATIVE_FUNC(clock_res_get), + REG_NATIVE_FUNC(clock_time_get), + REG_NATIVE_FUNC(environ_get), + REG_NATIVE_FUNC(environ_sizes_get), + REG_NATIVE_FUNC(fd_prestat_get), + REG_NATIVE_FUNC(fd_prestat_dir_name), + REG_NATIVE_FUNC(fd_close), + REG_NATIVE_FUNC(fd_datasync), + REG_NATIVE_FUNC(fd_pread), + REG_NATIVE_FUNC(fd_pwrite), + REG_NATIVE_FUNC(fd_read), + REG_NATIVE_FUNC(fd_renumber), + REG_NATIVE_FUNC(fd_seek), + REG_NATIVE_FUNC(fd_tell), + REG_NATIVE_FUNC(fd_fdstat_get), + REG_NATIVE_FUNC(fd_fdstat_set_flags), + REG_NATIVE_FUNC(fd_fdstat_set_rights), + REG_NATIVE_FUNC(fd_sync), + REG_NATIVE_FUNC(fd_write), + REG_NATIVE_FUNC(fd_advise), + REG_NATIVE_FUNC(fd_allocate), + REG_NATIVE_FUNC(path_create_directory), + REG_NATIVE_FUNC(path_link), + REG_NATIVE_FUNC(path_open), + REG_NATIVE_FUNC(fd_readdir), + REG_NATIVE_FUNC(path_readlink), + REG_NATIVE_FUNC(path_rename), + REG_NATIVE_FUNC(fd_filestat_get), + REG_NATIVE_FUNC(fd_filestat_set_times), + REG_NATIVE_FUNC(fd_filestat_set_size), + REG_NATIVE_FUNC(path_filestat_get), + REG_NATIVE_FUNC(path_filestat_set_times), + REG_NATIVE_FUNC(path_symlink), + REG_NATIVE_FUNC(path_unlink_file), + REG_NATIVE_FUNC(path_remove_directory), + REG_NATIVE_FUNC(poll_oneoff), + REG_NATIVE_FUNC(proc_exit), + REG_NATIVE_FUNC(proc_raise), + REG_NATIVE_FUNC(random_get), + REG_NATIVE_FUNC(sock_recv), + REG_NATIVE_FUNC(sock_send), + REG_NATIVE_FUNC(sock_shutdown), + REG_NATIVE_FUNC(sched_yield), +}; + +void* +wasi_native_func_lookup(const char *module_name, const char *func_name) +{ + uint32 size = sizeof(native_func_defs) / sizeof(WASMNativeFuncDef); + WASMNativeFuncDef *func_def = native_func_defs; + WASMNativeFuncDef *func_def_end = func_def + size; + + if (!module_name || !func_name) + return NULL; + + while (func_def < func_def_end) { + if (!strcmp(func_def->module_name, module_name) + && !strcmp(func_def->func_name, func_name)) + return (void*) (uintptr_t) func_def->func_ptr; + func_def++; + } + + return NULL; +} +#else +void* +wasi_native_func_lookup(const char *module_name, const char *func_name) +{ + return NULL; +} +#endif + diff --git a/core/iwasm/lib/native/libc/wasi_wrapper.h b/core/iwasm/lib/native/libc/wasi_wrapper.h new file mode 100644 index 000000000..288b4e175 --- /dev/null +++ b/core/iwasm/lib/native/libc/wasi_wrapper.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _WASI_WRAPPER_H +#define _WASI_WRAPPER_H + +#include "wasmtime_ssp.h" +#include "posix.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef __wasi_errno_t wasi_errno_t; +typedef __wasi_fd_t wasi_fd_t; +typedef __wasi_clockid_t wasi_clockid_t; +typedef __wasi_timestamp_t wasi_timestamp_t; +typedef __wasi_prestat_t wasi_prestat_t; +typedef __wasi_iovec_t wasi_iovec_t; +typedef __wasi_ciovec_t wasi_ciovec_t; +typedef __wasi_filetype_t wasi_filetype_t; +typedef __wasi_filesize_t wasi_filesize_t; +typedef __wasi_filedelta_t wasi_filedelta_t; +typedef __wasi_whence_t wasi_whence_t; +typedef __wasi_fdstat_t wasi_fdstat_t; +typedef __wasi_fdflags_t wasi_fdflags_t; +typedef __wasi_rights_t wasi_rights_t; +typedef __wasi_advice_t wasi_advice_t; +typedef __wasi_lookupflags_t wasi_lookupflags_t; +typedef __wasi_oflags_t wasi_oflags_t; +typedef __wasi_dircookie_t wasi_dircookie_t; +typedef __wasi_filestat_t wasi_filestat_t; +typedef __wasi_fstflags_t wasi_fstflags_t; +typedef __wasi_subscription_t wasi_subscription_t; +typedef __wasi_event_t wasi_event_t; +typedef __wasi_exitcode_t wasi_exitcode_t; +typedef __wasi_signal_t wasi_signal_t; +typedef __wasi_riflags_t wasi_riflags_t; +typedef __wasi_roflags_t wasi_roflags_t; +typedef __wasi_siflags_t wasi_siflags_t; +typedef __wasi_sdflags_t wasi_sdflags_t; +typedef __wasi_dircookie_t wasi_dircookie_t; +typedef __wasi_preopentype_t wasi_preopentype_t; + +void* +wasi_native_func_lookup(const char *module_name, const char *func_name); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _WASI_WRAPPER_H */ diff --git a/core/iwasm/products/alios-things/iwasm.mk b/core/iwasm/products/alios-things/iwasm.mk index 297738129..015a8fc76 100644 --- a/core/iwasm/products/alios-things/iwasm.mk +++ b/core/iwasm/products/alios-things/iwasm.mk @@ -26,6 +26,7 @@ $(NAME)_SOURCES := ${IWASM_ROOT}/runtime/utils/wasm_hashmap.c \ ${IWASM_ROOT}/lib/native/libc/libc_wrapper.c \ ${IWASM_ROOT}/lib/native/base/base_lib_export.c \ ${SHARED_LIB_ROOT}/platform/alios/bh_platform.c \ + ${SHARED_LIB_ROOT}/platform/alios/bh_definition.c \ ${SHARED_LIB_ROOT}/platform/alios/bh_assert.c \ ${SHARED_LIB_ROOT}/platform/alios/bh_thread.c \ ${SHARED_LIB_ROOT}/platform/alios/bh_math.c \ diff --git a/core/iwasm/products/alios-things/src/main.c b/core/iwasm/products/alios-things/src/main.c index e4f42f1c5..c5b3a8735 100644 --- a/core/iwasm/products/alios-things/src/main.c +++ b/core/iwasm/products/alios-things/src/main.c @@ -48,7 +48,7 @@ static char global_heap_buf[256 * 1024] = { 0 }; void iwasm_main(void *arg1) { uint8 *wasm_file_buf = NULL; - int wasm_file_size; + uint32 wasm_file_size; wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; char error_buf[128]; diff --git a/core/iwasm/products/alios-things/src/test_wasm.h b/core/iwasm/products/alios-things/src/test_wasm.h index a2f12706e..65b834798 100644 --- a/core/iwasm/products/alios-things/src/test_wasm.h +++ b/core/iwasm/products/alios-things/src/test_wasm.h @@ -3,6 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +/** + * The byte array buffer is the file content of a test wasm binary file, + * which is compiled by emcc or clang toolchain from C source file of: + * core/iwasm/app-samples/hello-world/main.c. + */ unsigned char wasm_test_file[] = { 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x06, 0x64, 0x79, 0x6C, 0x69, 0x6E, 0x6B, 0xC0, 0x80, 0x04, 0x04, 0x00, 0x00, 0x01, 0x13, 0x04, 0x60, 0x01, 0x7F, 0x00, 0x60, diff --git a/core/iwasm/products/darwin/CMakeLists.txt b/core/iwasm/products/darwin/CMakeLists.txt index 868ba37aa..deeae5671 100644 --- a/core/iwasm/products/darwin/CMakeLists.txt +++ b/core/iwasm/products/darwin/CMakeLists.txt @@ -17,7 +17,7 @@ endif () # Set BUILD_TARGET, currently values supported: # "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32" -if (NOT BUILD_TARGET) +if (NOT DEFINED BUILD_TARGET) if (CMAKE_SIZEOF_VOID_P EQUAL 8) # Build as X86_64 by default in 64-bit platform set (BUILD_TARGET "X86_64") @@ -60,6 +60,19 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8) endif () endif () +if (NOT DEFINED WASM_ENABLE_WASI) + # Enable wasi support by default + set (WASM_ENABLE_WASI 1) +endif () + +if (WASM_ENABLE_WASI EQUAL 1) + add_definitions(-DWASM_ENABLE_WASI=1) + add_definitions(-D_GNU_SOURCE) + message ("-- WASI enabled") +else () + message ("-- WASI disabled") +endif () + if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif (NOT CMAKE_BUILD_TYPE) @@ -82,6 +95,7 @@ enable_language (ASM) include (../../runtime/platform/${PLATFORM}/platform.cmake) include (../../runtime/utils/utils.cmake) include (../../runtime/vmcore-wasm/vmcore.cmake) +include (../../runtime/wasmtime-wasi-c/wasi.cmake) include (../../lib/native/base/wasm_lib_base.cmake) include (../../lib/native/libc/wasm_libc.cmake) include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake) @@ -92,6 +106,7 @@ add_library (vmlib ${WASM_PLATFORM_LIB_SOURCE} ${WASM_UTILS_LIB_SOURCE} ${VMCORE_LIB_SOURCE} + ${WASI_LIB_SOURCE} ${WASM_LIB_BASE_DIR}/base_lib_export.c ${WASM_LIBC_SOURCE} ${PLATFORM_SHARED_SOURCE} diff --git a/core/iwasm/products/darwin/main.c b/core/iwasm/products/darwin/main.c index f6b04c0e0..b92a439da 100644 --- a/core/iwasm/products/darwin/main.c +++ b/core/iwasm/products/darwin/main.c @@ -34,6 +34,15 @@ static int print_help() #endif wasm_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" " that runs commands in the form of `FUNC ARG...`\n"); +#if WASM_ENABLE_WASI != 0 + wasm_printf(" --env= Pass wasi environment variables with \"key=value\"\n"); + wasm_printf(" to the program, for example:\n"); + wasm_printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); + wasm_printf(" --dir= Grant wasi access to the given host directories\n"); + wasm_printf(" to the program, for example:\n"); + wasm_printf(" --dir= --dir=\n"); +#endif + return 1; } @@ -49,7 +58,7 @@ app_instance_main(wasm_module_inst_t module_inst) } static void* -app_instance_func(wasm_module_inst_t module_inst, const char *func_name) +app_instance_func(wasm_module_inst_t module_inst, char *func_name) { const char *exception; @@ -77,7 +86,7 @@ split_string(char *str, int *count) do { p = strtok(str, " "); str = NULL; - res = (char**) realloc(res, sizeof(char*) * (idx + 1)); + res = (char**) realloc(res, sizeof(char*) * (uint32)(idx + 1)); if (res == NULL) { return NULL; } @@ -120,6 +129,23 @@ app_instance_repl(wasm_module_inst_t module_inst) return NULL; } +static bool +validate_env_str(char *env) +{ + char *p = env; + int key_len = 0; + + while (*p != '\0' && *p != '=') { + key_len++; + p++; + } + + if (*p != '=' || key_len == 0) + return false; + + return true; +} + #define USE_GLOBAL_HEAP_BUF 0 #if USE_GLOBAL_HEAP_BUF != 0 @@ -129,9 +155,9 @@ static char global_heap_buf[10 * 1024 * 1024] = { 0 }; int main(int argc, char *argv[]) { char *wasm_file = NULL; - const char *func_name = NULL; + char *func_name = NULL; uint8 *wasm_file_buf = NULL; - int wasm_file_size; + uint32 wasm_file_size; wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; char error_buf[128]; @@ -139,6 +165,12 @@ int main(int argc, char *argv[]) int log_verbose_level = 1; #endif bool is_repl_mode = false; +#if WASM_ENABLE_WASI != 0 + const char *dir_list[8] = { NULL }; + uint32 dir_list_size = 0; + const char *env_list[8] = { NULL }; + uint32 env_list_size = 0; +#endif /* Process options. */ for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { @@ -159,6 +191,37 @@ int main(int argc, char *argv[]) #endif else if (!strcmp(argv[0], "--repl")) is_repl_mode = true; +#if WASM_ENABLE_WASI != 0 + else if (!strncmp(argv[0], "--dir=", 6)) { + if (argv[0][6] == '\0') + return print_help(); + if (dir_list_size >= sizeof(dir_list) / sizeof(char*)) { + wasm_printf("Only allow max dir number %d\n", + (int)(sizeof(dir_list) / sizeof(char*))); + return -1; + } + dir_list[dir_list_size++] = argv[0] + 6; + } + else if (!strncmp(argv[0], "--env=", 6)) { + char *tmp_env; + + if (argv[0][6] == '\0') + return print_help(); + if (env_list_size >= sizeof(env_list) / sizeof(char*)) { + wasm_printf("Only allow max env number %d\n", + (int)(sizeof(env_list) / sizeof(char*))); + return -1; + } + tmp_env = argv[0] + 6; + if (validate_env_str(tmp_env)) + env_list[env_list_size++] = tmp_env; + else { + wasm_printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", + tmp_env); + return print_help(); + } + } +#endif else return print_help(); } @@ -201,6 +264,14 @@ int main(int argc, char *argv[]) goto fail3; } +#if WASM_ENABLE_WASI != 0 + wasm_runtime_set_wasi_args(wasm_module, + dir_list, dir_list_size, + NULL, 0, + env_list, env_list_size, + argv, argc); +#endif + /* instantiate the module */ if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, 64 * 1024, /* stack size */ diff --git a/core/iwasm/products/linux-sgx/CMakeLists.txt b/core/iwasm/products/linux-sgx/CMakeLists.txt index 698abfac8..1ab2df1b7 100644 --- a/core/iwasm/products/linux-sgx/CMakeLists.txt +++ b/core/iwasm/products/linux-sgx/CMakeLists.txt @@ -22,7 +22,7 @@ if (NOT ("$ENV{VALGRIND}" STREQUAL "YES")) endif () # Set BUILD_TARGET, currently values supported: -if (NOT BUILD_TARGET) +if (NOT DEFINED BUILD_TARGET) if (CMAKE_SIZEOF_VOID_P EQUAL 8) # Build as X86_64 by default in 64-bit platform set (BUILD_TARGET "X86_64") @@ -62,6 +62,19 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8) endif () endif () +if (NOT DEFINED WASM_ENABLE_WASI) + # Disable wasi support by default + set (WASM_ENABLE_WASI 0) +endif () + +if (WASM_ENABLE_WASI EQUAL 1) + add_definitions(-DWASM_ENABLE_WASI=1) + add_definitions(-D_GNU_SOURCE) + message ("-- WASI enabled") +else () + message ("-- WASI disabled") +endif () + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -Wall -Wno-unused-parameter -Wno-pedantic") @@ -78,6 +91,7 @@ enable_language (ASM) include (../../runtime/platform/${PLATFORM}/platform.cmake) include (../../runtime/utils/utils.cmake) include (../../runtime/vmcore-wasm/vmcore.cmake) +include (../../runtime/wasmtime-wasi-c/wasi.cmake) include (../../lib/native/base/wasm_lib_base.cmake) include (../../lib/native/libc/wasm_libc.cmake) include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake) @@ -88,6 +102,7 @@ add_library (vmlib ${WASM_PLATFORM_LIB_SOURCE} ${WASM_UTILS_LIB_SOURCE} ${VMCORE_LIB_SOURCE} + ${WASI_LIB_SOURCE} ${WASM_LIB_BASE_DIR}/base_lib_export.c ${WASM_LIBC_SOURCE} ${PLATFORM_SHARED_SOURCE} @@ -95,3 +110,7 @@ add_library (vmlib ${UTILS_SHARED_SOURCE}) add_library (extlib ext_lib_export.c) + +set (copy_libs_cmd cp -a libvmlib.a libextlib.a ../enclave-sample/) +add_custom_target (copy_libs_to_enclave ALL COMMAND ${copy_libs_cmd} DEPENDS vmlib extlib) + diff --git a/core/iwasm/products/linux-sgx/enclave-sample/App/App.cpp b/core/iwasm/products/linux-sgx/enclave-sample/App/App.cpp new file mode 100644 index 000000000..9c4dcc5c9 --- /dev/null +++ b/core/iwasm/products/linux-sgx/enclave-sample/App/App.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include +#include +#include + +#include "Enclave_u.h" +#include "sgx_urts.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define TOKEN_FILENAME "enclave.token" +#define ENCLAVE_FILENAME "enclave.signed.so" +#define MAX_PATH FILENAME_MAX + +sgx_enclave_id_t g_eid = 0; + +void +ocall_print(const char* str) +{ + printf("%s", str); +} + +static void +print_error_message(sgx_status_t ret) +{ + printf("SGX error code: %d\n", ret); +} + +/* Initialize the enclave: + * Step 1: try to retrieve the launch token saved by last transaction + * Step 2: call sgx_create_enclave to initialize an enclave instance + * Step 3: save the launch token if it is updated + */ +static int +enclave_init(sgx_enclave_id_t *p_eid) + +{ + char token_path[MAX_PATH] = {'\0'}; + sgx_launch_token_t token = {0}; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + int updated = 0; + + /* Step 1: try to retrieve the launch token saved by last transaction + * if there is no token, then create a new one. + */ + /* try to get the token saved in $HOME */ + const char *home_dir = getpwuid(getuid())->pw_dir; + + if (home_dir != NULL && + (strlen(home_dir) + strlen("/") + sizeof(TOKEN_FILENAME) + 1) <= MAX_PATH) { + /* compose the token path */ + strncpy(token_path, home_dir, strlen(home_dir)); + strncat(token_path, "/", strlen("/")); + strncat(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME) + 1); + } + else { + /* if token path is too long or $HOME is NULL */ + strncpy(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME)); + } + + FILE *fp = fopen(token_path, "rb"); + if (fp == NULL && (fp = fopen(token_path, "wb")) == NULL) { + printf("Warning: Failed to create/open the launch token file \"%s\".\n", token_path); + } + + if (fp != NULL) { + /* read the token from saved file */ + size_t read_num = fread(token, 1, sizeof(sgx_launch_token_t), fp); + if (read_num != 0 && read_num != sizeof(sgx_launch_token_t)) { + /* if token is invalid, clear the buffer */ + memset(&token, 0x0, sizeof(sgx_launch_token_t)); + printf("Warning: Invalid launch token read from \"%s\".\n", token_path); + } + } + + /* Step 2: call sgx_create_enclave to initialize an enclave instance */ + /* Debug Support: set 2nd parameter to 1 */ + ret = sgx_create_enclave(ENCLAVE_FILENAME, SGX_DEBUG_FLAG, &token, &updated, p_eid, NULL); + if (ret != SGX_SUCCESS) { + print_error_message(ret); + if (fp != NULL) + fclose(fp); + return -1; + } + + /* Step 3: save the launch token if it is updated */ + if (updated == FALSE || fp == NULL) { + /* if the token is not updated, or file handler is invalid, do not perform saving */ + if (fp != NULL) fclose(fp); + return 0; + } + + /* reopen the file with write capablity */ + fp = freopen(token_path, "wb", fp); + if (fp == NULL) + return 0; + + size_t write_num = fwrite(token, 1, sizeof(sgx_launch_token_t), fp); + if (write_num != sizeof(sgx_launch_token_t)) + printf("Warning: Failed to save launch token to \"%s\".\n", token_path); + + fclose(fp); + return 0; +} + +int +main(int argc, char const *argv[]) +{ + if (enclave_init(&g_eid) < 0) { + std::cout << "Fail to initialize enclave." << std::endl; + return 1; + } + + ecall_iwasm_main(g_eid); + return 0; +} + diff --git a/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.config.xml b/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.config.xml new file mode 100644 index 000000000..a94d12f00 --- /dev/null +++ b/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.config.xml @@ -0,0 +1,12 @@ + + + 0 + 0 + 0x40000 + 0x100000 + 10 + 1 + 0 + 0 + 0xFFFFFFFF + diff --git a/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.cpp b/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.cpp new file mode 100644 index 000000000..36675b2d8 --- /dev/null +++ b/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include "Enclave_t.h" +#include "test_wasm.h" +#include "bh_memory.h" +#include "wasm_export.h" +#include "wasm_application.h" + +static char global_heap_buf[512 * 1024] = { 0 }; + +static int app_argc; +static char **app_argv; + +static void* +app_instance_main(wasm_module_inst_t module_inst) +{ + const char *exception; + + wasm_application_execute_main(module_inst, app_argc, app_argv); + if ((exception = wasm_runtime_get_exception(module_inst))) { + ocall_print(exception); + ocall_print("\n"); + } + return NULL; +} + +extern "C" { + +int bh_printf(const char *message, ...); + +typedef void (*bh_print_function_t)(const char* message); +extern void bh_set_print_function(bh_print_function_t pf); + +void enclave_print(const char *message) +{ + ocall_print(message); +} + +} + +void ecall_iwasm_main() +{ + bh_set_print_function(enclave_print); + + uint8_t *wasm_file_buf = NULL; + int wasm_file_size; + wasm_module_t wasm_module = NULL; + wasm_module_inst_t wasm_module_inst = NULL; + char error_buf[128]; + + if (bh_memory_init_with_pool(global_heap_buf, + sizeof(global_heap_buf)) != 0) { + ocall_print("Init global heap failed.\n"); + return; + } + + /* initialize runtime environment */ + if (!wasm_runtime_init()) + goto fail1; + + /* load WASM byte buffer from byte buffer of include file */ + wasm_file_buf = (uint8_t*) wasm_test_file; + wasm_file_size = sizeof(wasm_test_file); + + /* load WASM module */ + if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, + error_buf, sizeof(error_buf)))) { + ocall_print(error_buf); + ocall_print("\n"); + goto fail2; + } + + /* instantiate the module */ + if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, + 16 * 1024, + 16 * 1024, + error_buf, + sizeof(error_buf)))) { + ocall_print(error_buf); + ocall_print("\n"); + goto fail3; + } + + /* execute the main function of wasm app */ + app_instance_main(wasm_module_inst); + + /* destroy the module instance */ + wasm_runtime_deinstantiate(wasm_module_inst); + +fail3: + /* unload the module */ + wasm_runtime_unload(wasm_module); + +fail2: + /* destroy runtime environment */ + wasm_runtime_destroy(); + +fail1: + bh_memory_destroy(); +} + diff --git a/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.edl b/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.edl new file mode 100644 index 000000000..9228f5ac5 --- /dev/null +++ b/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.edl @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +enclave { + trusted { + /* define ECALLs here. */ + public void ecall_iwasm_main(void); + }; + + untrusted { + /* define OCALLs here. */ + void ocall_print([in, string]const char* str); + }; +}; diff --git a/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave_private.pem b/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave_private.pem new file mode 100644 index 000000000..529d07be3 --- /dev/null +++ b/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave_private.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4gIBAAKCAYEAroOogvsj/fZDZY8XFdkl6dJmky0lRvnWMmpeH41Bla6U1qLZ +AmZuyIF+mQC/cgojIsrBMzBxb1kKqzATF4+XwPwgKz7fmiddmHyYz2WDJfAjIveJ +ZjdMjM4+EytGlkkJ52T8V8ds0/L2qKexJ+NBLxkeQLfV8n1mIk7zX7jguwbCG1Pr +nEMdJ3Sew20vnje+RsngAzdPChoJpVsWi/K7cettX/tbnre1DL02GXc5qJoQYk7b +3zkmhz31TgFrd9VVtmUGyFXAysuSAb3EN+5VnHGr0xKkeg8utErea2FNtNIgua8H +ONfm9Eiyaav1SVKzPHlyqLtcdxH3I8Wg7yqMsaprZ1n5A1v/levxnL8+It02KseD +5HqV4rf/cImSlCt3lpRg8U5E1pyFQ2IVEC/XTDMiI3c+AR+w2jSRB3Bwn9zJtFlW +KHG3m1xGI4ck+Lci1JvWWLXQagQSPtZTsubxTQNx1gsgZhgv1JHVZMdbVlAbbRMC +1nSuJNl7KPAS/VfzAgEDAoIBgHRXxaynbVP5gkO0ug6Qw/E27wzIw4SmjsxG6Wpe +K7kfDeRskKxESdsA/xCrKkwGwhcx1iIgS5+Qscd1Yg+1D9X9asd/P7waPmWoZd+Z +AhlKwhdPsO7PiF3e1AzHhGQwsUTt/Y/aSI1MpHBvy2/s1h9mFCslOUxTmWw0oj/Q +ldIEgWeNR72CE2+jFIJIyml6ftnb6qzPiga8Bm48ubKh0kvySOqnkmnPzgh+JBD6 +JnBmtZbfPT97bwTT+N6rnPqOOApvfHPf15kWI8yDbprG1l4OCUaIUH1AszxLd826 +5IPM+8gINLRDP1MA6azECPjTyHXhtnSIBZCyWSVkc05vYmNXYUNiXWMajcxW9M02 +wKzFELO8NCEAkaTPxwo4SCyIjUxiK1LbQ9h8PSy4c1+gGP4LAMR8xqP4QKg6zdu9 +osUGG/xRe/uufgTBFkcjqBHtK5L5VI0jeNIUAgW/6iNbYXjBMJ0GfauLs+g1VsOm +WfdgXzsb9DYdMa0OXXHypmV4GwKBwQDUwQj8RKJ6c8cT4vcWCoJvJF00+RFL+P3i +Gx2DLERxRrDa8AVGfqaCjsR+3vLgG8V/py+z+dxZYSqeB80Qeo6PDITcRKoeAYh9 +xlT3LJOS+k1cJcEmlbbO2IjLkTmzSwa80fWexKu8/Xv6vv15gpqYl1ngYoqJM3pd +vzmTIOi7MKSZ0WmEQavrZj8zK4endE3v0eAEeQ55j1GImbypSf7Idh7wOXtjZ7WD +Dg6yWDrri+AP/L3gClMj8wsAxMV4ZR8CgcEA0fzDHkFa6raVOxWnObmRoDhAtE0a +cjUj976NM5yyfdf2MrKy4/RhdTiPZ6b08/lBC/+xRfV3xKVGzacm6QjqjZrUpgHC +0LKiZaMtccCJjLtPwQd0jGQEnKfMFaPsnhOc5y8qVkCzVOSthY5qhz0XNotHHFmJ +gffVgB0iqrMTvSL7IA2yqqpOqNRlhaYhNl8TiFP3gIeMtVa9rZy31JPgT2uJ+kfo +gV7sdTPEjPWZd7OshGxWpT6QfVDj/T9T7L6tAoHBAI3WBf2DFvxNL2KXT2QHAZ9t +k3imC4f7U+wSE6zILaDZyzygA4RUbwG0gv8/TJVn2P/Eynf76DuWHGlaiLWnCbSz +Az2DHBQBBaku409zDQym3j1ugMRjzzSQWzJg0SIyBH3hTmnYcn3+Uqcp/lEBvGW6 +O+rsXFt3pukqJmIV8HzLGGaLm62BHUeZf3dyWm+i3p/hQAL7Xvu04QW70xuGqdr5 +afV7p5eaeQIJXyGQJ0eylV/90+qxjMKiB1XYg6WYvwKBwQCL/ddpgOdHJGN8uRom +e7Zq0Csi3hGheMKlKbN3vcxT5U7MdyHtTZZOJbTvxKNNUNYH/8uD+PqDGNneb29G +BfGzvI3EASyLIcGZF3OhKwZd0jUrWk2y7Vhob91jwp2+t73vdMbkKyI4mHOuXvGv +fg95si9oO7EBT+Oqvhccd2J+F1IVXncccYnF4u5ZGWt5lLewN/pVr7MjjykeaHqN +t+rfnQam2psA6fL4zS2zTmZPzR2tnY8Y1GBTi0Ko1OKd1HMCgcAb5cB/7/AQlhP9 +yQa04PLH9ygQkKKptZp7dy5WcWRx0K/hAHRoi2aw1wZqfm7VBNu2SLcs90kCCCxp +6C5sfJi6b8NpNbIPC+sc9wsFr7pGo9SFzQ78UlcWYK2Gu2FxlMjonhka5hvo4zvg +WxlpXKEkaFt3gLd92m/dMqBrHfafH7VwOJY2zT3WIpjwuk0ZzmRg5p0pG/svVQEH +NZmwRwlopysbR69B/n1nefJ84UO50fLh5s5Zr3gBRwbWNZyzhXk= +-----END RSA PRIVATE KEY----- diff --git a/core/iwasm/products/linux-sgx/enclave-sample/Enclave/test_wasm.h b/core/iwasm/products/linux-sgx/enclave-sample/Enclave/test_wasm.h new file mode 100644 index 000000000..65b834798 --- /dev/null +++ b/core/iwasm/products/linux-sgx/enclave-sample/Enclave/test_wasm.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +/** + * The byte array buffer is the file content of a test wasm binary file, + * which is compiled by emcc or clang toolchain from C source file of: + * core/iwasm/app-samples/hello-world/main.c. + */ +unsigned char wasm_test_file[] = { 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x0D, 0x06, 0x64, 0x79, 0x6C, 0x69, 0x6E, 0x6B, 0xC0, 0x80, + 0x04, 0x04, 0x00, 0x00, 0x01, 0x13, 0x04, 0x60, 0x01, 0x7F, 0x00, 0x60, + 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x00, + 0x00, 0x02, 0x58, 0x06, 0x03, 0x65, 0x6E, 0x76, 0x05, 0x5F, 0x66, 0x72, + 0x65, 0x65, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x07, 0x5F, 0x6D, 0x61, + 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x07, 0x5F, + 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x02, 0x03, 0x65, 0x6E, 0x76, + 0x05, 0x5F, 0x70, 0x75, 0x74, 0x73, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, + 0x0D, 0x5F, 0x5F, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x5F, 0x62, 0x61, + 0x73, 0x65, 0x03, 0x7F, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, 0x65, + 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x01, 0x03, 0x04, 0x03, 0x02, 0x03, + 0x03, 0x06, 0x10, 0x03, 0x7F, 0x01, 0x41, 0x00, 0x0B, 0x7F, 0x01, 0x41, + 0x00, 0x0B, 0x7F, 0x00, 0x41, 0x1B, 0x0B, 0x07, 0x33, 0x04, 0x12, 0x5F, + 0x5F, 0x70, 0x6F, 0x73, 0x74, 0x5F, 0x69, 0x6E, 0x73, 0x74, 0x61, 0x6E, + 0x74, 0x69, 0x61, 0x74, 0x65, 0x00, 0x06, 0x05, 0x5F, 0x6D, 0x61, 0x69, + 0x6E, 0x00, 0x04, 0x0B, 0x72, 0x75, 0x6E, 0x50, 0x6F, 0x73, 0x74, 0x53, + 0x65, 0x74, 0x73, 0x00, 0x05, 0x04, 0x5F, 0x73, 0x74, 0x72, 0x03, 0x03, + 0x0A, 0xBA, 0x01, 0x03, 0x9E, 0x01, 0x01, 0x01, 0x7F, 0x23, 0x01, 0x21, + 0x00, 0x23, 0x01, 0x41, 0x10, 0x6A, 0x24, 0x01, 0x20, 0x00, 0x41, 0x08, + 0x6A, 0x21, 0x02, 0x23, 0x00, 0x41, 0x1B, 0x6A, 0x10, 0x03, 0x1A, 0x41, + 0x80, 0x08, 0x10, 0x01, 0x21, 0x01, 0x20, 0x01, 0x04, 0x7F, 0x20, 0x00, + 0x20, 0x01, 0x36, 0x02, 0x00, 0x23, 0x00, 0x20, 0x00, 0x10, 0x02, 0x1A, + 0x20, 0x01, 0x23, 0x00, 0x2C, 0x00, 0x0D, 0x3A, 0x00, 0x00, 0x20, 0x01, + 0x23, 0x00, 0x2C, 0x00, 0x0E, 0x3A, 0x00, 0x01, 0x20, 0x01, 0x23, 0x00, + 0x2C, 0x00, 0x0F, 0x3A, 0x00, 0x02, 0x20, 0x01, 0x23, 0x00, 0x2C, 0x00, + 0x10, 0x3A, 0x00, 0x03, 0x20, 0x01, 0x23, 0x00, 0x2C, 0x00, 0x11, 0x3A, + 0x00, 0x04, 0x20, 0x01, 0x23, 0x00, 0x2C, 0x00, 0x12, 0x3A, 0x00, 0x05, + 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x00, 0x23, 0x00, 0x41, 0x13, 0x6A, + 0x20, 0x02, 0x10, 0x02, 0x1A, 0x20, 0x01, 0x10, 0x00, 0x20, 0x00, 0x24, + 0x01, 0x41, 0x00, 0x05, 0x23, 0x00, 0x41, 0x28, 0x6A, 0x10, 0x03, 0x1A, + 0x20, 0x00, 0x24, 0x01, 0x41, 0x7F, 0x0B, 0x0B, 0x03, 0x00, 0x01, 0x0B, + 0x14, 0x00, 0x23, 0x00, 0x41, 0x40, 0x6B, 0x24, 0x01, 0x23, 0x01, 0x41, + 0x80, 0x80, 0x04, 0x6A, 0x24, 0x02, 0x10, 0x05, 0x0B, 0x0B, 0x3F, 0x01, + 0x00, 0x23, 0x00, 0x0B, 0x39, 0x62, 0x75, 0x66, 0x20, 0x70, 0x74, 0x72, + 0x3A, 0x20, 0x25, 0x70, 0x0A, 0x00, 0x31, 0x32, 0x33, 0x34, 0x0A, 0x00, + 0x62, 0x75, 0x66, 0x3A, 0x20, 0x25, 0x73, 0x00, 0x48, 0x65, 0x6C, 0x6C, + 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x00, 0x6D, 0x61, 0x6C, + 0x6C, 0x6F, 0x63, 0x20, 0x62, 0x75, 0x66, 0x20, 0x66, 0x61, 0x69, 0x6C, + 0x65, 0x64, 0x00, 0x50, 0x04, 0x6E, 0x61, 0x6D, 0x65, 0x01, 0x49, 0x07, + 0x00, 0x05, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x01, 0x07, 0x5F, 0x6D, 0x61, + 0x6C, 0x6C, 0x6F, 0x63, 0x02, 0x07, 0x5F, 0x70, 0x72, 0x69, 0x6E, 0x74, + 0x66, 0x03, 0x05, 0x5F, 0x70, 0x75, 0x74, 0x73, 0x04, 0x05, 0x5F, 0x6D, + 0x61, 0x69, 0x6E, 0x05, 0x0B, 0x72, 0x75, 0x6E, 0x50, 0x6F, 0x73, 0x74, + 0x53, 0x65, 0x74, 0x73, 0x06, 0x12, 0x5F, 0x5F, 0x70, 0x6F, 0x73, 0x74, + 0x5F, 0x69, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74, 0x69, 0x61, 0x74, 0x65, + 0x00, 0x20, 0x10, 0x73, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x4D, 0x61, 0x70, + 0x70, 0x69, 0x6E, 0x67, 0x55, 0x52, 0x4C, 0x0E, 0x61, 0x2E, 0x6F, 0x75, + 0x74, 0x2E, 0x77, 0x61, 0x73, 0x6D, 0x2E, 0x6D, 0x61, 0x70 }; diff --git a/core/iwasm/products/linux-sgx/enclave-sample/Makefile b/core/iwasm/products/linux-sgx/enclave-sample/Makefile new file mode 100644 index 000000000..8bb88f238 --- /dev/null +++ b/core/iwasm/products/linux-sgx/enclave-sample/Makefile @@ -0,0 +1,184 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +######## SGX SDK Settings ######## + +SGX_SDK ?= /opt/intel/sgxsdk +SGX_MODE ?= SIM +SGX_ARCH ?= x64 + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +######## App Settings ######## + +ifneq ($(SGX_MODE), HW) + Urts_Library_Name := sgx_urts_sim +else + Urts_Library_Name := sgx_urts +endif + +App_Cpp_Files := App/App.cpp +App_Include_Paths := -IApp -I$(SGX_SDK)/include + +App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths) + +# Three configuration modes - Debug, prerelease, release +# Debug - Macro DEBUG enabled. +# Prerelease - Macro NDEBUG and EDEBUG enabled. +# Release - Macro NDEBUG enabled. +ifeq ($(SGX_DEBUG), 1) + App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG +else + App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG +endif + +App_Cpp_Flags := $(App_C_Flags) -std=c++11 +App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread + +ifneq ($(SGX_MODE), HW) + App_Link_Flags += -lsgx_uae_service_sim +else + App_Link_Flags += -lsgx_uae_service +endif + +App_Cpp_Objects := $(App_Cpp_Files:.cpp=.o) + +App_Name := app + +######## Enclave Settings ######## + +ifneq ($(SGX_MODE), HW) + Trts_Library_Name := sgx_trts_sim + Service_Library_Name := sgx_tservice_sim +else + Trts_Library_Name := sgx_trts + Service_Library_Name := sgx_tservice +endif +Crypto_Library_Name := sgx_tcrypto + +WAMR_ROOT := $(CURDIR)/../../../../../ + +Enclave_Cpp_Files := Enclave/Enclave.cpp +Enclave_Include_Paths := -IEnclave -I$(WAMR_ROOT)/core/iwasm/runtime/include \ + -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport + +Enclave_C_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $(Enclave_Include_Paths) +Enclave_Cpp_Flags := $(Enclave_C_Flags) -std=c++03 -nostdinc++ +Enclave_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \ + -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \ + libvmlib.a libextlib.a \ + -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \ + -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ + -Wl,--defsym,__ImageBase=0 + +Enclave_Cpp_Objects := $(Enclave_Cpp_Files:.cpp=.o) + +Enclave_Name := enclave.so +Signed_Enclave_Name := enclave.signed.so +Enclave_Config_File := Enclave/Enclave.config.xml + +ifeq ($(SGX_MODE), HW) +ifneq ($(SGX_DEBUG), 1) +ifneq ($(SGX_PRERELEASE), 1) +Build_Mode = HW_RELEASE +endif +endif +endif + + +.PHONY: all run + +ifeq ($(Build_Mode), HW_RELEASE) +all: $(App_Name) $(Enclave_Name) + @echo "The project has been built in release hardware mode." + @echo "Please sign the $(Enclave_Name) first with your signing key before you run the $(App_Name) to launch and access the enclave." + @echo "To sign the enclave use the command:" + @echo " $(SGX_ENCLAVE_SIGNER) sign -key -enclave $(Enclave_Name) -out <$(Signed_Enclave_Name)> -config $(Enclave_Config_File)" + @echo "You can also sign the enclave using an external signing tool. See User's Guide for more details." + @echo "To build the project in simulation mode set SGX_MODE=SIM. To build the project in prerelease mode set SGX_PRERELEASE=1 and SGX_MODE=HW." +else +all: $(App_Name) $(Signed_Enclave_Name) +endif + +run: all +ifneq ($(Build_Mode), HW_RELEASE) + @$(CURDIR)/$(App_Name) + @echo "RUN => $(App_Name) [$(SGX_MODE)|$(SGX_ARCH), OK]" +endif + +######## App Objects ######## + +App/Enclave_u.c: $(SGX_EDGER8R) Enclave/Enclave.edl + @cd App && $(SGX_EDGER8R) --untrusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +App/Enclave_u.o: App/Enclave_u.c + @$(CC) $(App_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +App/%.o: App/%.cpp + @$(CXX) $(App_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +$(App_Name): App/Enclave_u.o $(App_Cpp_Objects) + @$(CXX) $^ -o $@ $(App_Link_Flags) + @echo "LINK => $@" + + +######## Enclave Objects ######## + +Enclave/Enclave_t.c: $(SGX_EDGER8R) Enclave/Enclave.edl + @cd Enclave && $(SGX_EDGER8R) --trusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +Enclave/Enclave_t.o: Enclave/Enclave_t.c + @$(CC) $(Enclave_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +Enclave/%.o: Enclave/%.cpp + @$(CXX) $(Enclave_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +$(Enclave_Name): Enclave/Enclave_t.o $(Enclave_Cpp_Objects) + @$(CXX) $^ -o $@ $(Enclave_Link_Flags) + @echo "LINK => $@" + +$(Signed_Enclave_Name): $(Enclave_Name) + @$(SGX_ENCLAVE_SIGNER) sign -key Enclave/Enclave_private.pem -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File) + @echo "SIGN => $@" + +.PHONY: clean + +clean: + @rm -f $(App_Name) $(Enclave_Name) $(Signed_Enclave_Name) $(App_Cpp_Objects) App/Enclave_u.* $(Enclave_Cpp_Objects) Enclave/Enclave_t.* diff --git a/core/iwasm/products/linux/CMakeLists.txt b/core/iwasm/products/linux/CMakeLists.txt index ab36f22e8..8d1b64279 100644 --- a/core/iwasm/products/linux/CMakeLists.txt +++ b/core/iwasm/products/linux/CMakeLists.txt @@ -17,7 +17,7 @@ endif () # Set BUILD_TARGET, currently values supported: # "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32" -if (NOT BUILD_TARGET) +if (NOT DEFINED BUILD_TARGET) if (CMAKE_SIZEOF_VOID_P EQUAL 8) # Build as X86_64 by default in 64-bit platform set (BUILD_TARGET "X86_64") @@ -60,6 +60,18 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8) endif () endif () +if (NOT DEFINED WASM_ENABLE_WASI) + # Enable wasi support by default + set (WASM_ENABLE_WASI 1) +endif () + +if (WASM_ENABLE_WASI EQUAL 1) + add_definitions(-DWASM_ENABLE_WASI=1) + message ("-- WASI enabled") +else () + message ("-- WASI disabled") +endif () + if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif (NOT CMAKE_BUILD_TYPE) @@ -80,16 +92,26 @@ enable_language (ASM) include (../../runtime/platform/${PLATFORM}/platform.cmake) include (../../runtime/utils/utils.cmake) include (../../runtime/vmcore-wasm/vmcore.cmake) +include (../../runtime/wasmtime-wasi-c/wasi.cmake) include (../../lib/native/base/wasm_lib_base.cmake) include (../../lib/native/libc/wasm_libc.cmake) include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake) include (${SHARED_LIB_DIR}/mem-alloc/mem_alloc.cmake) include (${SHARED_LIB_DIR}/utils/shared_utils.cmake) +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") +#set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wsign-conversion") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch=thunk -mfunction-return=thunk -mindirect-branch-register") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong --param ssp-buffer-size=4") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pie -fPIE -ftrapv -D_FORTIFY_SOURCE=2") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now") +#message ("-- CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}") + add_library (vmlib ${WASM_PLATFORM_LIB_SOURCE} ${WASM_UTILS_LIB_SOURCE} ${VMCORE_LIB_SOURCE} + ${WASI_LIB_SOURCE} ${WASM_LIB_BASE_DIR}/base_lib_export.c ${WASM_LIBC_SOURCE} ${PLATFORM_SHARED_SOURCE} diff --git a/core/iwasm/products/linux/main.c b/core/iwasm/products/linux/main.c index 481e8365c..44a3cc713 100644 --- a/core/iwasm/products/linux/main.c +++ b/core/iwasm/products/linux/main.c @@ -32,6 +32,15 @@ static int print_help() #endif wasm_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" " that runs commands in the form of `FUNC ARG...`\n"); +#if WASM_ENABLE_WASI != 0 + wasm_printf(" --env= Pass wasi environment variables with \"key=value\"\n"); + wasm_printf(" to the program, for example:\n"); + wasm_printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); + wasm_printf(" --dir= Grant wasi access to the given host directories\n"); + wasm_printf(" to the program, for example:\n"); + wasm_printf(" --dir= --dir=\n"); +#endif + return 1; } @@ -104,7 +113,7 @@ split_string(char *str, int *count) do { p = strtok(str, " "); str = NULL; - res = (char**) realloc(res, sizeof(char*) * (idx + 1)); + res = (char**) realloc(res, sizeof(char*) * (uint32)(idx + 1)); if (res == NULL) { return NULL; } @@ -147,6 +156,23 @@ app_instance_repl(wasm_module_inst_t module_inst) return NULL; } +static bool +validate_env_str(char *env) +{ + char *p = env; + int key_len = 0; + + while (*p != '\0' && *p != '=') { + key_len++; + p++; + } + + if (*p != '=' || key_len == 0) + return false; + + return true; +} + #define USE_GLOBAL_HEAP_BUF 0 #if USE_GLOBAL_HEAP_BUF != 0 @@ -158,7 +184,7 @@ int main(int argc, char *argv[]) char *wasm_file = NULL; const char *func_name = NULL; uint8 *wasm_file_buf = NULL; - int wasm_file_size; + uint32 wasm_file_size; wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; char error_buf[128]; @@ -166,6 +192,12 @@ int main(int argc, char *argv[]) int log_verbose_level = 1; #endif bool is_repl_mode = false; +#if WASM_ENABLE_WASI != 0 + const char *dir_list[8] = { NULL }; + uint32 dir_list_size = 0; + const char *env_list[8] = { NULL }; + uint32 env_list_size = 0; +#endif /* Process options. */ for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { @@ -186,6 +218,37 @@ int main(int argc, char *argv[]) #endif else if (!strcmp(argv[0], "--repl")) is_repl_mode = true; +#if WASM_ENABLE_WASI != 0 + else if (!strncmp(argv[0], "--dir=", 6)) { + if (argv[0][6] == '\0') + return print_help(); + if (dir_list_size >= sizeof(dir_list) / sizeof(char*)) { + wasm_printf("Only allow max dir number %d\n", + (int)(sizeof(dir_list) / sizeof(char*))); + return -1; + } + dir_list[dir_list_size++] = argv[0] + 6; + } + else if (!strncmp(argv[0], "--env=", 6)) { + char *tmp_env; + + if (argv[0][6] == '\0') + return print_help(); + if (env_list_size >= sizeof(env_list) / sizeof(char*)) { + wasm_printf("Only allow max env number %d\n", + (int)(sizeof(env_list) / sizeof(char*))); + return -1; + } + tmp_env = argv[0] + 6; + if (validate_env_str(tmp_env)) + env_list[env_list_size++] = tmp_env; + else { + wasm_printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", + tmp_env); + return print_help(); + } + } +#endif else return print_help(); } @@ -228,6 +291,14 @@ int main(int argc, char *argv[]) goto fail3; } +#if WASM_ENABLE_WASI != 0 + wasm_runtime_set_wasi_args(wasm_module, + dir_list, dir_list_size, + NULL, 0, + env_list, env_list_size, + argv, argc); +#endif + /* instantiate the module */ if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, 64 * 1024, /* stack size */ diff --git a/core/iwasm/products/vxworks/CMakeLists.txt b/core/iwasm/products/vxworks/CMakeLists.txt index 20e2fcf10..bd42cb155 100644 --- a/core/iwasm/products/vxworks/CMakeLists.txt +++ b/core/iwasm/products/vxworks/CMakeLists.txt @@ -24,7 +24,7 @@ endif () # "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32", "GENERAL" #set (BUILD_TARGET "X86_64") -if (NOT BUILD_TARGET) +if (NOT DEFINED BUILD_TARGET) if (CMAKE_SIZEOF_VOID_P EQUAL 8) # Build as X86_64 by default in 64-bit platform # if BUILD_TARGET isn't set @@ -77,6 +77,19 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8) endif () endif () +if (NOT DEFINED WASM_ENABLE_WASI) + # Enable wasi support by default + set (WASM_ENABLE_WASI 1) +endif () + +if (WASM_ENABLE_WASI EQUAL 1) + add_definitions(-DWASM_ENABLE_WASI=1) + add_definitions(-D_GNU_SOURCE) + message ("-- WASI enabled") +else () + message ("-- WASI disabled") +endif () + if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif (NOT CMAKE_BUILD_TYPE) @@ -97,6 +110,7 @@ enable_language (ASM) include (../../runtime/platform/${PLATFORM}/platform.cmake) include (../../runtime/utils/utils.cmake) include (../../runtime/vmcore-wasm/vmcore.cmake) +include (../../runtime/wasmtime-wasi-c/wasi.cmake) include (../../lib/native/base/wasm_lib_base.cmake) include (../../lib/native/libc/wasm_libc.cmake) include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake) @@ -107,6 +121,7 @@ add_library (vmlib ${WASM_PLATFORM_LIB_SOURCE} ${WASM_UTILS_LIB_SOURCE} ${VMCORE_LIB_SOURCE} + ${WASI_LIB_SOURCE} ${WASM_LIB_BASE_DIR}/base_lib_export.c ${WASM_LIBC_SOURCE} ${PLATFORM_SHARED_SOURCE} diff --git a/core/iwasm/products/vxworks/main.c b/core/iwasm/products/vxworks/main.c index df8513be2..6d35e1f96 100644 --- a/core/iwasm/products/vxworks/main.c +++ b/core/iwasm/products/vxworks/main.c @@ -32,6 +32,15 @@ static int print_help() #endif wasm_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" " that runs commands in the form of `FUNC ARG...`\n"); +#if WASM_ENABLE_WASI != 0 + wasm_printf(" --env= Pass wasi environment variables with \"key=value\"\n"); + wasm_printf(" to the program, for example:\n"); + wasm_printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); + wasm_printf(" --dir= Grant wasi access to the given host directories\n"); + wasm_printf(" to the program, for example:\n"); + wasm_printf(" --dir= --dir=\n"); +#endif + return 1; } @@ -104,7 +113,7 @@ split_string(char *str, int *count) do { p = strtok(str, " "); str = NULL; - res = (char**) realloc(res, sizeof(char*) * (idx + 1)); + res = (char**) realloc(res, sizeof(char*) * (uint32)(idx + 1)); if (res == NULL) { return NULL; } @@ -147,6 +156,23 @@ app_instance_repl(wasm_module_inst_t module_inst) return NULL; } +static bool +validate_env_str(char *env) +{ + char *p = env; + int key_len = 0; + + while (*p != '\0' && *p != '=') { + key_len++; + p++; + } + + if (*p != '=' || key_len == 0) + return false; + + return true; +} + static char global_heap_buf[512 * 1024] = { 0 }; int main(int argc, char *argv[]) @@ -154,7 +180,7 @@ int main(int argc, char *argv[]) char *wasm_file = NULL; const char *func_name = NULL; uint8 *wasm_file_buf = NULL; - int wasm_file_size; + uint32 wasm_file_size; wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; char error_buf[128]; @@ -162,6 +188,12 @@ int main(int argc, char *argv[]) int log_verbose_level = 1; #endif bool is_repl_mode = false; +#if WASM_ENABLE_WASI != 0 + const char *dir_list[8] = { NULL }; + uint32 dir_list_size = 0; + const char *env_list[8] = { NULL }; + uint32 env_list_size = 0; +#endif /* Process options. */ for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { @@ -182,6 +214,37 @@ int main(int argc, char *argv[]) #endif else if (!strcmp(argv[0], "--repl")) is_repl_mode = true; +#if WASM_ENABLE_WASI != 0 + else if (!strncmp(argv[0], "--dir=", 6)) { + if (argv[0][6] == '\0') + return print_help(); + if (dir_list_size >= sizeof(dir_list) / sizeof(char*)) { + wasm_printf("Only allow max dir number %d\n", + (int)(sizeof(dir_list) / sizeof(char*))); + return -1; + } + dir_list[dir_list_size++] = argv[0] + 6; + } + else if (!strncmp(argv[0], "--env=", 6)) { + char *tmp_env; + + if (argv[0][6] == '\0') + return print_help(); + if (env_list_size >= sizeof(env_list) / sizeof(char*)) { + wasm_printf("Only allow max env number %d\n", + (int)(sizeof(env_list) / sizeof(char*))); + return -1; + } + tmp_env = argv[0] + 6; + if (validate_env_str(tmp_env)) + env_list[env_list_size++] = tmp_env; + else { + wasm_printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", + tmp_env); + return print_help(); + } + } +#endif else return print_help(); } @@ -217,6 +280,14 @@ int main(int argc, char *argv[]) goto fail3; } +#if WASM_ENABLE_WASI != 0 + wasm_runtime_set_wasi_args(wasm_module, + dir_list, dir_list_size, + NULL, 0, + env_list, env_list_size, + argv, argc); +#endif + /* instantiate the module */ if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, 16 * 1024, /* stack size */ diff --git a/core/iwasm/products/zephyr/simple/CMakeLists.txt b/core/iwasm/products/zephyr/simple/CMakeLists.txt index 1ba22bff6..6c2fecc0d 100644 --- a/core/iwasm/products/zephyr/simple/CMakeLists.txt +++ b/core/iwasm/products/zephyr/simple/CMakeLists.txt @@ -8,11 +8,13 @@ project(NONE) enable_language (ASM) +set (PLATFORM "zephyr") + add_definitions (-DNVALGRIND) # Build as X86_32 by default, change to "ARM_32", "MIPS_32" or "XTENSA_32" # if we want to support arm, mips or xtensa -if (NOT BUILD_TARGET) +if (NOT DEFINED BUILD_TARGET) set (BUILD_TARGET "X86_32") endif () @@ -35,33 +37,29 @@ message ("-- Build as target ${BUILD_TARGET}") set (IWASM_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/iwasm) set (SHARED_LIB_ROOT ${IWASM_ROOT}/../shared-lib) -include_directories (${IWASM_ROOT}/runtime/include - ${IWASM_ROOT}/runtime/platform/include - ${IWASM_ROOT}/runtime/platform/zephyr - ${IWASM_ROOT}/runtime/vmcore-wasm - ${SHARED_LIB_ROOT}/include - ${SHARED_LIB_ROOT}/platform/include - ${SHARED_LIB_ROOT}/platform/zephyr) +include (${IWASM_ROOT}/runtime/platform/${PLATFORM}/platform.cmake) +include (${IWASM_ROOT}/runtime/utils/utils.cmake) +include (${IWASM_ROOT}/runtime/vmcore-wasm/vmcore.cmake) +include (${IWASM_ROOT}/runtime/wasmtime-wasi-c/wasi.cmake) +include (${IWASM_ROOT}/lib/native/base/wasm_lib_base.cmake) +include (${IWASM_ROOT}/lib/native/libc/wasm_libc.cmake) +include (${SHARED_LIB_ROOT}/platform/${PLATFORM}/shared_platform.cmake) +include (${SHARED_LIB_ROOT}/mem-alloc/mem_alloc.cmake) +include (${SHARED_LIB_ROOT}/utils/shared_utils.cmake) -set (IWASM_SRCS ${IWASM_ROOT}/runtime/utils/wasm_hashmap.c - ${IWASM_ROOT}/runtime/utils/wasm_log.c - ${IWASM_ROOT}/runtime/utils/wasm_dlfcn.c - ${IWASM_ROOT}/runtime/platform/zephyr/wasm_native.c - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_application.c - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_interp.c - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_loader.c - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_runtime.c - ${IWASM_ROOT}/runtime/vmcore-wasm/invokeNative_general.c - ${IWASM_ROOT}/lib/native/libc/libc_wrapper.c - ${IWASM_ROOT}/lib/native/base/base_lib_export.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_platform.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_assert.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_thread.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_math.c - ${SHARED_LIB_ROOT}/mem-alloc/bh_memory.c - ${SHARED_LIB_ROOT}/mem-alloc/mem_alloc.c - ${SHARED_LIB_ROOT}/mem-alloc/ems/ems_kfc.c - ${SHARED_LIB_ROOT}/mem-alloc/ems/ems_alloc.c - ${SHARED_LIB_ROOT}/mem-alloc/ems/ems_hmu.c) +set (VM_LIB_SRCS + ${WASM_PLATFORM_LIB_SOURCE} + ${WASM_UTILS_LIB_SOURCE} + ${VMCORE_LIB_SOURCE} + ${WASI_LIB_SOURCE} + ${WASM_LIB_BASE_DIR}/base_lib_export.c + ${WASM_LIBC_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE}) + +target_sources(app PRIVATE + ${VM_LIB_SRCS} + src/main.c + src/ext_lib_export.c) -target_sources(app PRIVATE ${IWASM_SRCS} src/main.c src/ext_lib_export.c) diff --git a/core/iwasm/products/zephyr/simple/src/main.c b/core/iwasm/products/zephyr/simple/src/main.c index 42e21d107..7492d878e 100644 --- a/core/iwasm/products/zephyr/simple/src/main.c +++ b/core/iwasm/products/zephyr/simple/src/main.c @@ -53,7 +53,7 @@ static char global_heap_buf[CONFIG_GLOBAL_HEAP_BUF_SIZE] = { 0 }; void iwasm_main(void *arg1, void *arg2, void *arg3) { uint8 *wasm_file_buf = NULL; - int wasm_file_size; + uint32 wasm_file_size; wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; char error_buf[128]; diff --git a/core/iwasm/products/zephyr/simple/src/test_wasm.h b/core/iwasm/products/zephyr/simple/src/test_wasm.h index a2f12706e..65b834798 100644 --- a/core/iwasm/products/zephyr/simple/src/test_wasm.h +++ b/core/iwasm/products/zephyr/simple/src/test_wasm.h @@ -3,6 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +/** + * The byte array buffer is the file content of a test wasm binary file, + * which is compiled by emcc or clang toolchain from C source file of: + * core/iwasm/app-samples/hello-world/main.c. + */ unsigned char wasm_test_file[] = { 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x06, 0x64, 0x79, 0x6C, 0x69, 0x6E, 0x6B, 0xC0, 0x80, 0x04, 0x04, 0x00, 0x00, 0x01, 0x13, 0x04, 0x60, 0x01, 0x7F, 0x00, 0x60, diff --git a/core/iwasm/runtime/include/bh_memory.h b/core/iwasm/runtime/include/bh_memory.h index b2c091d2f..4b3aa86db 100644 --- a/core/iwasm/runtime/include/bh_memory.h +++ b/core/iwasm/runtime/include/bh_memory.h @@ -45,7 +45,7 @@ void bh_memory_destroy(); * Get the pool size of memory, if memory is initialized with allocator, * return 1GB by default. */ -int bh_memory_pool_size(); +unsigned bh_memory_pool_size(); #if BEIHAI_ENABLE_MEMORY_PROFILING == 0 diff --git a/core/iwasm/runtime/include/wasm_export.h b/core/iwasm/runtime/include/wasm_export.h index 98be2c915..21e55df99 100644 --- a/core/iwasm/runtime/include/wasm_export.h +++ b/core/iwasm/runtime/include/wasm_export.h @@ -110,6 +110,15 @@ wasm_runtime_load_from_sections(wasm_section_list_t section_list, void wasm_runtime_unload(wasm_module_t module); +#if WASM_ENABLE_WASI != 0 +void +wasm_runtime_set_wasi_args(wasm_module_t module, + const char *dir_list[], uint32 dir_count, + const char *map_dir_list[], uint32 map_dir_count, + const char *env[], uint32 env_count, + char *argv[], int argc); +#endif + /** * Instantiate a WASM module. * diff --git a/core/iwasm/runtime/platform/linux-sgx/wasm_native.c b/core/iwasm/runtime/platform/linux-sgx/wasm_native.c index 40e70e15c..b59b99d07 100644 --- a/core/iwasm/runtime/platform/linux-sgx/wasm_native.c +++ b/core/iwasm/runtime/platform/linux-sgx/wasm_native.c @@ -12,6 +12,7 @@ #include "wasm_log.h" #include "wasm_memory.h" #include "wasm_platform_log.h" +#include "bh_common.h" #include #include @@ -91,7 +92,7 @@ __syscall3_wrapper(WASMModuleInstance *module_inst, uint32 iov_len; } *vec; int32 vec_offset = arg2, str_offset; - uint32 iov_count = arg3, i; + uint32 iov_count = (uint32)arg3, i; int32 count = 0; char *iov_base, *str; @@ -110,7 +111,7 @@ __syscall3_wrapper(WASMModuleInstance *module_inst, str = addr_app_to_native(str_offset); - memcpy(str, iov_base, vec->iov_len); + bh_memcpy_s(str, vec->iov_len + 1, iov_base, vec->iov_len); str[vec->iov_len] = '\0'; count += wasm_printf("%s", str); @@ -219,7 +220,7 @@ EMCC_SYSCALL_WRAPPER3(221) EMCC_SYSCALL_WRAPPER5(140) -static int32 +static uint32 getTotalMemory_wrapper(WASMModuleInstance *module_inst) { WASMMemoryInstance *memory = module_inst->default_memory; diff --git a/core/iwasm/runtime/platform/linux/platform.cmake b/core/iwasm/runtime/platform/linux/platform.cmake index e687f8305..4924a3fb9 100644 --- a/core/iwasm/runtime/platform/linux/platform.cmake +++ b/core/iwasm/runtime/platform/linux/platform.cmake @@ -1,7 +1,7 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -add_definitions (-D__POSIX__ -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=199309L) +add_definitions (-D__POSIX__ -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200809L -D_BSD_SOURCE) set (PLATFORM_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}) diff --git a/core/iwasm/runtime/platform/linux/wasm_native.c b/core/iwasm/runtime/platform/linux/wasm_native.c index 22c68151c..435f19753 100644 --- a/core/iwasm/runtime/platform/linux/wasm_native.c +++ b/core/iwasm/runtime/platform/linux/wasm_native.c @@ -12,6 +12,7 @@ #include "wasm_log.h" #include "wasm_memory.h" #include "wasm_platform_log.h" +#include "bh_common.h" #include #include @@ -92,7 +93,7 @@ __syscall3_wrapper(WASMModuleInstance *module_inst, return 0; wsz = (struct winsize*)addr_app_to_native(arg3); - return syscall(54, arg1, arg2, wsz); + return (int32)syscall(54, arg1, arg2, wsz); } case 146: /* writev */ @@ -104,7 +105,7 @@ __syscall3_wrapper(WASMModuleInstance *module_inst, uint32 iov_len; } *vec; int32 vec_offset = arg2, str_offset; - uint32 iov_count = arg3, i; + uint32 iov_count = (uint32)arg3, i; int32 count = 0; char *iov_base, *str; @@ -123,7 +124,7 @@ __syscall3_wrapper(WASMModuleInstance *module_inst, str = addr_app_to_native(str_offset); - memcpy(str, iov_base, vec->iov_len); + bh_memcpy_s(str, vec->iov_len + 1, iov_base, vec->iov_len); str[vec->iov_len] = '\0'; count += wasm_printf("%s", str); @@ -232,7 +233,7 @@ EMCC_SYSCALL_WRAPPER3(221) EMCC_SYSCALL_WRAPPER5(140) -static int32 +static uint32 getTotalMemory_wrapper(WASMModuleInstance *module_inst) { WASMMemoryInstance *memory = module_inst->default_memory; diff --git a/core/iwasm/runtime/platform/vxworks/platform.cmake b/core/iwasm/runtime/platform/vxworks/platform.cmake index e687f8305..4924a3fb9 100644 --- a/core/iwasm/runtime/platform/vxworks/platform.cmake +++ b/core/iwasm/runtime/platform/vxworks/platform.cmake @@ -1,7 +1,7 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -add_definitions (-D__POSIX__ -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=199309L) +add_definitions (-D__POSIX__ -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200809L -D_BSD_SOURCE) set (PLATFORM_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}) diff --git a/core/iwasm/runtime/platform/zephyr/platform.cmake b/core/iwasm/runtime/platform/zephyr/platform.cmake new file mode 100644 index 000000000..4924a3fb9 --- /dev/null +++ b/core/iwasm/runtime/platform/zephyr/platform.cmake @@ -0,0 +1,14 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +add_definitions (-D__POSIX__ -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200809L -D_BSD_SOURCE) + +set (PLATFORM_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}) + +include_directories(${PLATFORM_LIB_DIR}) +include_directories(${PLATFORM_LIB_DIR}/../include) + +file (GLOB_RECURSE source_all ${PLATFORM_LIB_DIR}/*.c) + +set (WASM_PLATFORM_LIB_SOURCE ${source_all}) + diff --git a/core/iwasm/runtime/utils/wasm_hashmap.c b/core/iwasm/runtime/utils/wasm_hashmap.c index adaef5d80..04e9c82d7 100644 --- a/core/iwasm/runtime/utils/wasm_hashmap.c +++ b/core/iwasm/runtime/utils/wasm_hashmap.c @@ -37,7 +37,7 @@ wasm_hash_map_create(uint32 size, bool use_lock, ValueDestroyFunc value_destroy_func) { HashMap *map; - uint32 total_size; + uint64 total_size; if (size > HASH_MAP_MAX_SIZE) { LOG_ERROR("HashMap create failed: size is too large.\n"); @@ -51,19 +51,21 @@ wasm_hash_map_create(uint32 size, bool use_lock, } total_size = offsetof(HashMap, elements) + - sizeof(HashMapElem) * size + + sizeof(HashMapElem) * (uint64)size + (use_lock ? sizeof(korp_mutex) : 0); - if (!(map = wasm_malloc(total_size))) { + if (total_size >= UINT32_MAX + || !(map = wasm_malloc((uint32)total_size))) { LOG_ERROR("HashMap create failed: alloc memory failed.\n"); return NULL; } - memset(map, 0, total_size); + memset(map, 0, (uint32)total_size); if (use_lock) { map->lock = (korp_mutex*) - ((uint8*)map + offsetof(HashMap, elements) + sizeof(HashMapElem) * size); + ((uint8*)map + offsetof(HashMap, elements) + + sizeof(HashMapElem) * size); if (ws_mutex_init(map->lock, false)) { LOG_ERROR("HashMap create failed: init map lock failed.\n"); wasm_free(map); diff --git a/core/iwasm/runtime/vmcore-wasm/wasm.h b/core/iwasm/runtime/vmcore-wasm/wasm.h index f90771031..72004d84b 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm.h +++ b/core/iwasm/runtime/vmcore-wasm/wasm.h @@ -217,6 +217,19 @@ typedef struct BlockAddr { #define BLOCK_ADDR_CACHE_SIZE 64 #define BLOCK_ADDR_CONFLICT_SIZE 4 +#if WASM_ENABLE_WASI != 0 +typedef struct WASIArguments { + const char **dir_list; + uint32 dir_count; + const char **map_dir_list; + uint32 map_dir_count; + const char **env; + uint32 env_count; + const char **argv; + uint32 argc; +} WASIArguments; +#endif + typedef struct WASMModule { uint32 type_count; uint32 import_count; @@ -255,16 +268,19 @@ typedef struct WASMModule { #else BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE]; #endif + +#if WASM_ENABLE_WASI != 0 + WASIArguments wasi_args; + bool is_wasi_module; +#endif } WASMModule; typedef struct WASMBranchBlock { uint8 block_type; uint8 return_type; uint8 *start_addr; - uint8 *else_addr; uint8 *end_addr; uint32 *frame_sp; - uint8 *frame_ref; } WASMBranchBlock; typedef struct WASMSection { @@ -299,7 +315,7 @@ align_uint (unsigned v, unsigned b) inline static uint32 wasm_string_hash(const char *str) { - unsigned h = strlen(str); + unsigned h = (unsigned)strlen(str); const uint8 *p = (uint8*)str; const uint8 *end = p + h; @@ -356,11 +372,11 @@ wasm_value_type_cell_num(uint8 value_type) inline static uint16 wasm_get_cell_num(const uint8 *types, uint32 type_count) { - uint16 cell_num = 0; + uint32 cell_num = 0; uint32 i; for (i = 0; i < type_count; i++) cell_num += wasm_value_type_cell_num(types[i]); - return cell_num; + return (uint16)cell_num; } inline static uint16 diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_application.c b/core/iwasm/runtime/vmcore-wasm/wasm_application.c index 8fcabde72..20ed543ea 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_application.c +++ b/core/iwasm/runtime/vmcore-wasm/wasm_application.c @@ -15,6 +15,7 @@ #include "wasm_log.h" #include "wasm_memory.h" #include "wasm_platform_log.h" +#include "bh_common.h" static WASMFunctionInstance* @@ -55,17 +56,55 @@ check_main_func_type(const WASMType *type) return true; } +#if WASM_ENABLE_WASI != 0 +static WASMFunctionInstance * +lookup_wasi_start_function(WASMModuleInstance *module_inst) +{ + WASMFunctionInstance *func = NULL; + uint32 i; + for (i = 0; i < module_inst->export_func_count; i++) { + if (!strcmp(module_inst->export_functions[i].name, "_start")) { + func = module_inst->export_functions[i].function; + if (func->u.func->func_type->param_count != 0 + || func->u.func->func_type->result_count != 0) { + LOG_ERROR("Lookup wasi _start function failed: " + "invalid function type.\n"); + return NULL; + } + return func; + } + } + return NULL; +} +#endif + bool wasm_application_execute_main(WASMModuleInstance *module_inst, int argc, char *argv[]) { - WASMFunctionInstance *func = resolve_main_function(module_inst); + WASMFunctionInstance *func; uint32 argc1 = 0, argv1[2] = { 0 }; - uint32 total_argv_size = 0, total_size; + uint32 total_argv_size = 0; + uint64 total_size; int32 argv_buf_offset, i; - char *argv_buf, *p; + char *argv_buf, *p, *p_end; int32 *argv_offsets; +#if WASM_ENABLE_WASI != 0 + if (module_inst->module->is_wasi_module) { + /* In wasi mode, we should call function named "_start" + which initializes the wasi envrionment and then calls + the actual main function. Directly call main function + may cause exception thrown. */ + if ((func = lookup_wasi_start_function(module_inst))) + return wasm_runtime_call_wasm(module_inst, NULL, + func, 0, NULL); + /* if no start function is found, we execute + the main function as normal */ + } +#endif + + func = resolve_main_function(module_inst); if (!func || func->is_import_func) return false; @@ -74,25 +113,28 @@ wasm_application_execute_main(WASMModuleInstance *module_inst, if (func->u.func->func_type->param_count) { for (i = 0; i < argc; i++) - total_argv_size += strlen(argv[i]) + 1; + total_argv_size += (uint32)(strlen(argv[i]) + 1); total_argv_size = align_uint(total_argv_size, 4); - total_size = total_argv_size + sizeof(int32) * argc; + total_size = (uint64)total_argv_size + sizeof(int32) * (uint64)argc; - if (!(argv_buf_offset = wasm_runtime_module_malloc(module_inst, total_size))) + if (total_size >= UINT32_MAX + || !(argv_buf_offset = + wasm_runtime_module_malloc(module_inst, (uint32)total_size))) return false; argv_buf = p = wasm_runtime_addr_app_to_native(module_inst, argv_buf_offset); argv_offsets = (int32*)(p + total_argv_size); + p_end = p + total_size; for (i = 0; i < argc; i++) { - memcpy(p, argv[i], strlen(argv[i]) + 1); - argv_offsets[i] = argv_buf_offset + (p - argv_buf); + bh_memcpy_s(p, (uint32)(p_end - p), argv[i], (uint32)(strlen(argv[i]) + 1)); + argv_offsets[i] = argv_buf_offset + (int32)(p - argv_buf); p += strlen(argv[i]) + 1; } argc1 = 2; - argv1[0] = argc; + argv1[0] = (uint32)argc; argv1[1] = (uint32)wasm_runtime_addr_native_to_app(module_inst, argv_offsets); } @@ -165,6 +207,7 @@ wasm_application_execute_func(WASMModuleInstance *module_inst, WASMType *type; uint32 argc1, *argv1; int32 i, p; + uint64 total_size; const char *exception; wasm_assert(argc >= 0); @@ -181,15 +224,16 @@ wasm_application_execute_func(WASMModuleInstance *module_inst, } argc1 = func->param_cell_num; - argv1 = wasm_malloc(sizeof(uint32) * (argc1 > 2 ? argc1 : 2)); - if (argv1 == NULL) { + total_size = sizeof(uint32) * (uint64)(argc1 > 2 ? argc1 : 2); + if (total_size >= UINT32_MAX + || (!(argv1 = wasm_malloc((uint32)total_size)))) { LOG_ERROR("Wasm prepare param failed: malloc failed.\n"); return false; } /* Parse arguments */ for (i = 0, p = 0; i < argc; i++) { - char *endptr; + char *endptr = NULL; wasm_assert(argv[i] != NULL); if (argv[i][0] == '\0') { LOG_ERROR("Wasm prepare param failed: invalid num (%s).\n", argv[i]); @@ -197,7 +241,7 @@ wasm_application_execute_func(WASMModuleInstance *module_inst, } switch (type->types[i]) { case VALUE_TYPE_I32: - argv1[p++] = strtoul(argv[i], &endptr, 0); + argv1[p++] = (uint32)strtoul(argv[i], &endptr, 0); break; case VALUE_TYPE_I64: { @@ -217,7 +261,7 @@ wasm_application_execute_func(WASMModuleInstance *module_inst, if (endptr[0] == ':') { uint32 sig; union ieee754_float u; - sig = strtoul(endptr + 1, &endptr, 0); + sig = (uint32)strtoul(endptr + 1, &endptr, 0); u.f = f32; if (is_little_endian()) u.ieee.ieee_little_endian.mantissa = sig; @@ -244,11 +288,11 @@ wasm_application_execute_func(WASMModuleInstance *module_inst, ud.d = u.val; if (is_little_endian()) { ud.ieee.ieee_little_endian.mantissa0 = sig >> 32; - ud.ieee.ieee_little_endian.mantissa1 = sig; + ud.ieee.ieee_little_endian.mantissa1 = (uint32)sig; } else { ud.ieee.ieee_big_endian.mantissa0 = sig >> 32; - ud.ieee.ieee_big_endian.mantissa1 = sig; + ud.ieee.ieee_big_endian.mantissa1 = (uint32)sig; } u.val = ud.d; } @@ -258,7 +302,7 @@ wasm_application_execute_func(WASMModuleInstance *module_inst, break; } } - if (*endptr != '\0' && *endptr != '_') { + if (endptr && *endptr != '\0' && *endptr != '_') { LOG_ERROR("Wasm prepare param failed: invalid num (%s).\n", argv[i]); goto fail; } diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_interp.c b/core/iwasm/runtime/vmcore-wasm/wasm_interp.c index 47e51e75b..86373d1cd 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_interp.c +++ b/core/iwasm/runtime/vmcore-wasm/wasm_interp.c @@ -33,7 +33,7 @@ typedef float64 CellType_F64; #else /* WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 */ #define PUT_I64_TO_ADDR(addr, value) do { \ union { int64 val; uint32 parts[2]; } u; \ - u.val = (value); \ + u.val = (int64)(value); \ (addr)[0] = u.parts[0]; \ (addr)[1] = u.parts[1]; \ } while (0) @@ -110,36 +110,36 @@ GET_F64_FROM_ADDR (uint32 *addr) } while (0) static inline uint32 -rotl32(uint32 n, unsigned int c) +rotl32(uint32 n, uint32 c) { - const unsigned int mask = (31); + const uint32 mask = (31); c = c % 32; c &= mask; return (n<>( (-c)&mask )); } static inline uint32 -rotr32(uint32 n, unsigned int c) +rotr32(uint32 n, uint32 c) { - const unsigned int mask = (31); + const uint32 mask = (31); c = c % 32; c &= mask; return (n>>c) | (n<<( (-c)&mask )); } static inline uint64 -rotl64(uint64 n, unsigned int c) +rotl64(uint64 n, uint64 c) { - const unsigned int mask = (63); + const uint64 mask = (63); c = c % 64; c &= mask; return (n<>( (-c)&mask )); } static inline uint64 -rotr64(uint64 n, unsigned int c) +rotr64(uint64 n, uint64 c) { - const unsigned int mask = (63); + const uint64 mask = (63); c = c % 64; c &= mask; return (n>>c) | (n<<( (-c)&mask )); @@ -237,21 +237,6 @@ popcount64(uint64 u) return ret; } -static inline WASMGlobalInstance* -get_global(const WASMModuleInstance *module, uint32 global_idx) -{ - if (global_idx >= module->global_count) - return NULL; - - return module->globals + global_idx; -} - -static inline uint8* -get_global_addr(WASMMemoryInstance *memory, WASMGlobalInstance *global) -{ - return memory->global_data + global->data_offset; -} - static uint64 read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) { @@ -300,7 +285,6 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) frame_csp->block_type = type; \ frame_csp->return_type = ret_type; \ frame_csp->start_addr = start; \ - frame_csp->else_addr = else_; \ frame_csp->end_addr = end; \ frame_csp->frame_sp = frame_sp; \ frame_csp++; \ @@ -315,7 +299,7 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) #define POP_F64() (frame_sp -= 2, GET_F64_FROM_ADDR(frame_sp)) #define POP_CSP_CHECK_OVERFLOW(n) do { \ - wasm_assert(frame_csp - n >= frame->csp_bottom); \ + wasm_assert(frame_csp - n >= frame->csp_bottom); \ } while (0) #define POP_CSP() do { \ @@ -355,28 +339,28 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) #define LOCAL_I32(n) (*(int32*)(local_off(n))) #define SET_LOCAL_I32(N, val) do { \ - int n = (N); \ + uint32 n = (N); \ *(int32*)(local_off(n)) = (int32)(val); \ } while (0) #define LOCAL_F32(n) (*(float32*)(local_off(n))) #define SET_LOCAL_F32(N, val) do { \ - int n = (N); \ + uint32 n = (N); \ *(float32*)(local_off(n)) = (float32)(val); \ } while (0) #define LOCAL_I64(n) (GET_I64_FROM_ADDR(local_off(n))) #define SET_LOCAL_I64(N, val) do { \ - int n = (N); \ + uint32 n = (N); \ PUT_I64_TO_ADDR(local_off(n), val); \ } while (0) #define LOCAL_F64(n) (GET_F64_FROM_ADDR(local_off(n))) #define SET_LOCAL_F64(N, val) do { \ - int n = (N); \ + uint32 n = (N); \ PUT_F64_TO_ADDR(local_off(n), val); \ } while (0) @@ -428,15 +412,15 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) p += _off; \ } while (0) -#define RECOVER_CONTEXT(new_frame) do { \ - frame = (new_frame); \ - cur_func = frame->function; \ - prev_frame = frame->prev_frame; \ - frame_ip = frame->ip; \ - frame_ip_end = wasm_runtime_get_func_code_end(cur_func); \ - frame_lp = frame->lp; \ - frame_sp = frame->sp; \ - frame_csp = frame->csp; \ +#define RECOVER_CONTEXT(new_frame) do { \ + frame = (new_frame); \ + cur_func = frame->function; \ + prev_frame = frame->prev_frame; \ + frame_ip = frame->ip; \ + frame_ip_end = wasm_runtime_get_func_code_end(cur_func); \ + frame_lp = frame->lp; \ + frame_sp = frame->sp; \ + frame_csp = frame->csp; \ } while (0) #if WASM_ENABLE_LABELS_AS_VALUES != 0 @@ -445,56 +429,56 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) #define GET_OPCODE() (void)0 #endif -#define DEF_OP_LOAD(operation) do { \ - uint32 offset, flags, addr; \ - GET_OPCODE(); \ - read_leb_uint32(frame_ip, frame_ip_end, flags); \ - read_leb_uint32(frame_ip, frame_ip_end, offset); \ - addr = POP_I32(); \ - CHECK_MEMORY_OVERFLOW(); \ - operation; \ - (void)flags; \ +#define DEF_OP_LOAD(operation) do { \ + uint32 offset, flags, addr; \ + GET_OPCODE(); \ + read_leb_uint32(frame_ip, frame_ip_end, flags); \ + read_leb_uint32(frame_ip, frame_ip_end, offset); \ + addr = POP_I32(); \ + CHECK_MEMORY_OVERFLOW(); \ + operation; \ + (void)flags; \ } while (0) -#define DEF_OP_STORE(sval_type, sval_op_type, operation) do { \ - uint32 offset, flags, addr; \ - sval_type sval; \ - GET_OPCODE(); \ - read_leb_uint32(frame_ip, frame_ip_end, flags); \ - read_leb_uint32(frame_ip, frame_ip_end, offset); \ - sval = POP_##sval_op_type(); \ - addr = POP_I32(); \ - CHECK_MEMORY_OVERFLOW(); \ - operation; \ - (void)flags; \ +#define DEF_OP_STORE(sval_type, sval_op_type, operation) do { \ + uint32 offset, flags, addr; \ + sval_type sval; \ + GET_OPCODE(); \ + read_leb_uint32(frame_ip, frame_ip_end, flags); \ + read_leb_uint32(frame_ip, frame_ip_end, offset); \ + sval = POP_##sval_op_type(); \ + addr = POP_I32(); \ + CHECK_MEMORY_OVERFLOW(); \ + operation; \ + (void)flags; \ } while (0) -#define DEF_OP_I_CONST(ctype, src_op_type) do { \ - ctype cval; \ - read_leb_##ctype(frame_ip, frame_ip_end, cval); \ - PUSH_##src_op_type(cval); \ +#define DEF_OP_I_CONST(ctype, src_op_type) do { \ + ctype cval; \ + read_leb_##ctype(frame_ip, frame_ip_end, cval); \ + PUSH_##src_op_type(cval); \ } while (0) -#define DEF_OP_EQZ(src_op_type) do { \ - uint32 val; \ - val = POP_##src_op_type() == 0; \ - PUSH_I32(val); \ +#define DEF_OP_EQZ(src_op_type) do { \ + int32 val; \ + val = POP_##src_op_type() == 0; \ + PUSH_I32(val); \ } while (0) -#define DEF_OP_CMP(src_type, src_op_type, cond) do { \ - uint32 res; \ - src_type val1, val2; \ - val2 = POP_##src_op_type(); \ - val1 = POP_##src_op_type(); \ - res = val1 cond val2; \ - PUSH_I32(res); \ +#define DEF_OP_CMP(src_type, src_op_type, cond) do { \ + uint32 res; \ + src_type val1, val2; \ + val2 = (src_type)POP_##src_op_type(); \ + val1 = (src_type)POP_##src_op_type(); \ + res = val1 cond val2; \ + PUSH_I32(res); \ } while (0) -#define DEF_OP_BIT_COUNT(src_type, src_op_type, operation) do { \ - src_type val1, val2; \ - val1 = POP_##src_op_type(); \ - val2 = operation(val1); \ - PUSH_##src_op_type(val2); \ +#define DEF_OP_BIT_COUNT(src_type, src_op_type, operation) do { \ + src_type val1, val2; \ + val1 = (src_type)POP_##src_op_type(); \ + val2 = (src_type)operation(val1); \ + PUSH_##src_op_type(val2); \ } while (0) #define DEF_OP_NUMERIC(src_type1, src_type2, src_op_type, operation) do { \ @@ -503,50 +487,48 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) *(src_type2*)(frame_sp); \ } while (0) -#define DEF_OP_MATH(src_type, src_op_type, method) do { \ - src_type val; \ - val = POP_##src_op_type(); \ - PUSH_##src_op_type(method(val)); \ +#define DEF_OP_MATH(src_type, src_op_type, method) do { \ + src_type val; \ + val = POP_##src_op_type(); \ + PUSH_##src_op_type(method(val)); \ } while (0) -#define DEF_OP_TRUNC(dst_type, dst_op_type, src_type, src_op_type, \ - min_cond, max_cond) do { \ - src_type value = POP_##src_op_type(); \ - if (isnan(value)) { \ - wasm_runtime_set_exception(module, \ - "invalid conversion to integer"); \ - goto got_exception; \ - } \ - else if (value min_cond || value max_cond) { \ - wasm_runtime_set_exception(module, "integer overflow"); \ - goto got_exception; \ - } \ - PUSH_##dst_op_type(((dst_type)value)); \ +#define DEF_OP_TRUNC(dst_type, dst_op_type, src_type, src_op_type, \ + min_cond, max_cond) do { \ + src_type value = POP_##src_op_type(); \ + if (isnan(value)) { \ + wasm_runtime_set_exception(module, \ + "invalid conversion to integer"); \ + goto got_exception; \ + } \ + else if (value min_cond || value max_cond) { \ + wasm_runtime_set_exception(module, "integer overflow"); \ + goto got_exception; \ + } \ + PUSH_##dst_op_type(((dst_type)value)); \ } while (0) -#define DEF_OP_CONVERT(dst_type, dst_op_type, \ - src_type, src_op_type) do { \ - dst_type value = (dst_type)(src_type)POP_##src_op_type(); \ - PUSH_##dst_op_type(value); \ +#define DEF_OP_CONVERT(dst_type, dst_op_type, \ + src_type, src_op_type) do { \ + dst_type value = (dst_type)(src_type)POP_##src_op_type(); \ + PUSH_##dst_op_type(value); \ } while (0) #define GET_LOCAL_INDEX_AND_TYPE() do { \ - param_count = cur_func->u.func->func_type->param_count; \ - local_count = cur_func->u.func->local_count; \ + uint32 param_count = cur_func->param_count; \ read_leb_uint32(frame_ip, frame_ip_end, local_idx); \ - wasm_assert(local_idx < param_count + local_count); \ + wasm_assert(local_idx < param_count + cur_func->local_count); \ if (local_idx < param_count) \ - local_type = cur_func->u.func->func_type->types[local_idx]; \ + local_type = cur_func->param_types[local_idx]; \ else \ - local_type = \ - cur_func->u.func->local_types[local_idx - param_count]; \ + local_type = cur_func->local_types[local_idx - param_count]; \ } while (0) static inline int32 sign_ext_8_32(int8 val) { if (val & 0x80) - return val | 0xffffff00; + return (int32)val | (int32)0xffffff00; return val; } @@ -554,7 +536,7 @@ static inline int32 sign_ext_16_32(int16 val) { if (val & 0x8000) - return val | 0xffff0000; + return (int32)val | (int32)0xffff0000; return val; } @@ -562,7 +544,7 @@ static inline int64 sign_ext_8_64(int8 val) { if (val & 0x80) - return val | 0xffffffffffffff00; + return (int64)val | (int64)0xffffffffffffff00; return val; } @@ -570,15 +552,15 @@ static inline int64 sign_ext_16_64(int16 val) { if (val & 0x8000) - return val | 0xffffffffffff0000; + return (int64)val | (int64)0xffffffffffff0000; return val; } static inline int64 sign_ext_32_64(int32 val) { - if (val & 0x80000000) - return val | 0xffffffff00000000; + if (val & (int32)0x80000000) + return (int64)val | (int64)0xffffffff00000000; return val; } @@ -674,10 +656,12 @@ wasm_interp_call_func_bytecode(WASMThread *self, WASMMemoryInstance *memory = module->default_memory; uint32 memory_data_size = memory ? NumBytesPerPage * memory->cur_page_count : 0; - uint32 heap_base_offset = memory ? memory->heap_base_offset : 0; + uint32 heap_base_offset = memory ? (uint32)memory->heap_base_offset : 0; uint32 heap_data_size = memory - ? memory->heap_data_end - memory->heap_data : 0; + ? (uint32)(memory->heap_data_end - memory->heap_data) : 0; WASMTableInstance *table = module->default_table; + WASMGlobalInstance *globals = module->globals; + uint8 *global_data = memory ? memory->global_data : NULL; uint8 opcode_IMPDEP2 = WASM_OP_IMPDEP2; WASMInterpFrame *frame = NULL; /* Points to this special opcode so as to jump to the @@ -690,10 +674,10 @@ wasm_interp_call_func_bytecode(WASMThread *self, uint8 opcode, block_ret_type; uint32 *depths = NULL; uint32 depth_buf[BR_TABLE_TMP_BUF_LEN]; - uint32 i, depth, cond, count, fidx, tidx, frame_size = 0, all_cell_num = 0; + uint32 i, depth, cond, count, fidx, tidx, frame_size = 0; + uint64 all_cell_num = 0; int32 didx, val; - uint8 *else_addr, *end_addr; - uint8 *maddr = NULL; + uint8 *else_addr, *end_addr, *maddr = NULL; #if WASM_ENABLE_LABELS_AS_VALUES != 0 #define HANDLE_OPCODE(op) &&HANDLE_##op @@ -723,7 +707,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP_END (); HANDLE_OP (WASM_OP_BLOCK): - read_leb_uint32(frame_ip, frame_ip_end, block_ret_type); + read_leb_uint8(frame_ip, frame_ip_end, block_ret_type); if (!wasm_loader_find_block_addr(module->module, frame_ip, frame_ip_end, @@ -738,7 +722,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP_END (); HANDLE_OP (WASM_OP_LOOP): - read_leb_uint32(frame_ip, frame_ip_end, block_ret_type); + read_leb_uint8(frame_ip, frame_ip_end, block_ret_type); if (!wasm_loader_find_block_addr(module->module, frame_ip, frame_ip_end, @@ -753,7 +737,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP_END (); HANDLE_OP (WASM_OP_IF): - read_leb_uint32(frame_ip, frame_ip_end, block_ret_type); + read_leb_uint8(frame_ip, frame_ip_end, block_ret_type); if (!wasm_loader_find_block_addr(module->module, frame_ip, frame_ip_end, @@ -764,7 +748,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, goto got_exception; } - cond = POP_I32(); + cond = (uint32)POP_I32(); PUSH_CSP(BLOCK_TYPE_IF, block_ret_type, frame_ip, else_addr, end_addr); @@ -806,7 +790,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP (WASM_OP_BR_IF): read_leb_uint32(frame_ip, frame_ip_end, depth); - cond = POP_I32(); + cond = (uint32)POP_I32(); if (cond) POP_CSP_N(depth); HANDLE_OP_END (); @@ -816,7 +800,9 @@ wasm_interp_call_func_bytecode(WASMThread *self, if (count <= BR_TABLE_TMP_BUF_LEN) depths = depth_buf; else { - if (!(depths = wasm_malloc(sizeof(uint32) * count))) { + uint64 total_size = sizeof(uint32) * (uint64)count; + if (total_size >= UINT32_MAX + || !(depths = wasm_malloc((uint32)total_size))) { wasm_runtime_set_exception(module, "WASM interp failed: " "allocate memory failed."); @@ -916,7 +902,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP (WASM_OP_SELECT_32): { - cond = POP_I32(); + cond = (uint32)POP_I32(); frame_sp--; if (!cond) *(frame_sp - 1) = *frame_sp; @@ -925,7 +911,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP (WASM_OP_SELECT_64): { - cond = POP_I32(); + cond = (uint32)POP_I32(); frame_sp -= 2; if (!cond) { *(frame_sp - 2) = *frame_sp; @@ -937,7 +923,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, /* variable instructions */ HANDLE_OP (WASM_OP_GET_LOCAL): { - uint32 local_idx, param_count, local_count; + uint32 local_idx; uint8 local_type; GET_LOCAL_INDEX_AND_TYPE(); @@ -960,13 +946,12 @@ wasm_interp_call_func_bytecode(WASMThread *self, "invalid local type"); goto got_exception; } - (void)local_count; HANDLE_OP_END (); } HANDLE_OP (WASM_OP_SET_LOCAL): { - uint32 local_idx, param_count, local_count; + uint32 local_idx; uint8 local_type; GET_LOCAL_INDEX_AND_TYPE(); @@ -989,13 +974,12 @@ wasm_interp_call_func_bytecode(WASMThread *self, "invalid local type"); goto got_exception; } - (void)local_count; HANDLE_OP_END (); } HANDLE_OP (WASM_OP_TEE_LOCAL): { - uint32 local_idx, param_count, local_count; + uint32 local_idx; uint8 local_type; GET_LOCAL_INDEX_AND_TYPE(); @@ -1017,7 +1001,6 @@ wasm_interp_call_func_bytecode(WASMThread *self, wasm_runtime_set_exception(module, "invalid local type"); goto got_exception; } - (void)local_count; HANDLE_OP_END (); } @@ -1025,24 +1008,26 @@ wasm_interp_call_func_bytecode(WASMThread *self, { WASMGlobalInstance *global; uint32 global_idx; + uint8 *global_addr; read_leb_uint32(frame_ip, frame_ip_end, global_idx); - global = get_global(module, global_idx); - wasm_assert(global && global_idx < module->global_count); + wasm_assert(global_idx < module->global_count); + global = globals + global_idx; + global_addr = global_data + global->data_offset; switch (global->type) { case VALUE_TYPE_I32: - PUSH_I32(*(uint32*)get_global_addr(memory, global)); + PUSH_I32(*(uint32*)global_addr); break; case VALUE_TYPE_F32: - PUSH_F32(*(float32*)get_global_addr(memory, global)); + PUSH_F32(*(float32*)global_addr); break; case VALUE_TYPE_I64: - PUSH_I64(*(uint64*)get_global_addr(memory, global)); + PUSH_I64(GET_I64_FROM_ADDR((uint32*)global_addr)); break; case VALUE_TYPE_F64: - PUSH_F64(*(float64*)get_global_addr(memory, global)); + PUSH_F64(GET_F64_FROM_ADDR((uint32*)global_addr)); break; default: wasm_runtime_set_exception(module, "invalid global type"); @@ -1059,13 +1044,13 @@ wasm_interp_call_func_bytecode(WASMThread *self, read_leb_uint32(frame_ip, frame_ip_end, global_idx); - global = get_global(module, global_idx); - wasm_assert(global && global_idx < module->global_count); + wasm_assert(global_idx < module->global_count); + global = globals + global_idx; + global_addr = global_data + global->data_offset; - global_addr = get_global_addr(memory, global); switch (global->type) { case VALUE_TYPE_I32: - *(uint32*)global_addr = POP_I32(); + *(int32*)global_addr = POP_I32(); break; case VALUE_TYPE_F32: *(float32*)global_addr = POP_F32(); @@ -1103,7 +1088,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, GET_OPCODE(); read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, offset); - addr = POP_I32(); + addr = (uint32)POP_I32(); CHECK_MEMORY_OVERFLOW(); #if WASM_ENABLE_LABELS_AS_VALUES != 0 static const void *handle_load_table[] = { @@ -1184,7 +1169,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, offset); frame_sp--; - addr = POP_I32(); + addr = (uint32)POP_I32(); CHECK_MEMORY_OVERFLOW(); *(uint32*)maddr = frame_sp[1]; (void)flags; @@ -1198,7 +1183,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, offset); frame_sp -= 2; - addr = POP_I32(); + addr = (uint32)POP_I32(); CHECK_MEMORY_OVERFLOW(); *(uint32*)maddr = frame_sp[1]; *((uint32*)maddr + 1) = frame_sp[2]; @@ -1215,12 +1200,12 @@ wasm_interp_call_func_bytecode(WASMThread *self, GET_OPCODE(); read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, offset); - sval = POP_I32(); - addr = POP_I32(); + sval = (uint32)POP_I32(); + addr = (uint32)POP_I32(); CHECK_MEMORY_OVERFLOW(); switch (opcode) { case WASM_OP_I32_STORE: - *(int32*)maddr = sval; + *(uint32*)maddr = sval; break; case WASM_OP_I32_STORE8: *(uint8*)maddr = (uint8)sval; @@ -1243,8 +1228,8 @@ wasm_interp_call_func_bytecode(WASMThread *self, GET_OPCODE(); read_leb_uint32(frame_ip, frame_ip_end, flags); read_leb_uint32(frame_ip, frame_ip_end, offset); - sval = POP_I64(); - addr = POP_I32(); + sval = (uint64)POP_I64(); + addr = (uint32)POP_I32(); CHECK_MEMORY_OVERFLOW(); switch (opcode) { case WASM_OP_I64_STORE: @@ -1279,13 +1264,13 @@ wasm_interp_call_func_bytecode(WASMThread *self, uint32 reserved, delta, prev_page_count = memory->cur_page_count; read_leb_uint32(frame_ip, frame_ip_end, reserved); - delta = POP_I32(); + delta = (uint32)POP_I32(); if (!wasm_runtime_enlarge_memory(module, delta)) { /* fail to memory.grow, return -1 */ PUSH_I32(-1); if (wasm_runtime_get_exception(module)) { - printf("%s\n", wasm_runtime_get_exception(module)); + bh_printf("%s\n", wasm_runtime_get_exception(module)); wasm_runtime_set_exception(module, NULL); } } @@ -1295,6 +1280,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, /* update the memory instance ptr */ memory = module->default_memory; memory_data_size = NumBytesPerPage * memory->cur_page_count; + global_data = memory->global_data; } (void)reserved; @@ -1514,8 +1500,8 @@ wasm_interp_call_func_bytecode(WASMThread *self, { uint32 a, b; - b = POP_I32(); - a = POP_I32(); + b = (uint32)POP_I32(); + a = (uint32)POP_I32(); if (b == 0) { wasm_runtime_set_exception(module, "integer divide by zero"); goto got_exception; @@ -1546,8 +1532,8 @@ wasm_interp_call_func_bytecode(WASMThread *self, { uint32 a, b; - b = POP_I32(); - a = POP_I32(); + b = (uint32)POP_I32(); + a = (uint32)POP_I32(); if (b == 0) { wasm_runtime_set_exception(module, "integer divide by zero"); goto got_exception; @@ -1584,8 +1570,8 @@ wasm_interp_call_func_bytecode(WASMThread *self, { uint32 a, b; - b = POP_I32(); - a = POP_I32(); + b = (uint32)POP_I32(); + a = (uint32)POP_I32(); PUSH_I32(rotl32(a, b)); HANDLE_OP_END (); } @@ -1594,8 +1580,8 @@ wasm_interp_call_func_bytecode(WASMThread *self, { uint32 a, b; - b = POP_I32(); - a = POP_I32(); + b = (uint32)POP_I32(); + a = (uint32)POP_I32(); PUSH_I32(rotr32(a, b)); HANDLE_OP_END (); } @@ -1647,8 +1633,8 @@ wasm_interp_call_func_bytecode(WASMThread *self, { uint64 a, b; - b = POP_I64(); - a = POP_I64(); + b = (uint64)POP_I64(); + a = (uint64)POP_I64(); if (b == 0) { wasm_runtime_set_exception(module, "integer divide by zero"); goto got_exception; @@ -1679,8 +1665,8 @@ wasm_interp_call_func_bytecode(WASMThread *self, { uint64 a, b; - b = POP_I64(); - a = POP_I64(); + b = (uint64)POP_I64(); + a = (uint64)POP_I64(); if (b == 0) { wasm_runtime_set_exception(module, "integer divide by zero"); goto got_exception; @@ -1717,8 +1703,8 @@ wasm_interp_call_func_bytecode(WASMThread *self, { uint64 a, b; - b = POP_I64(); - a = POP_I64(); + b = (uint64)POP_I64(); + a = (uint64)POP_I64(); PUSH_I64(rotl64(a, b)); HANDLE_OP_END (); } @@ -1727,8 +1713,8 @@ wasm_interp_call_func_bytecode(WASMThread *self, { uint64 a, b; - b = POP_I64(); - a = POP_I64(); + b = (uint64)POP_I64(); + a = (uint64)POP_I64(); PUSH_I64(rotr64(a, b)); HANDLE_OP_END (); } @@ -2092,14 +2078,23 @@ wasm_interp_call_func_bytecode(WASMThread *self, goto got_exception; } else { + WASMFunction *cur_wasm_func = cur_func->u.func; WASMType *func_type; uint8 ret_type; - all_cell_num = cur_func->param_cell_num + cur_func->local_cell_num - + cur_func->u.func->max_stack_cell_num - + cur_func->u.func->max_block_num * sizeof(WASMBranchBlock) / 4; - frame_size = wasm_interp_interp_frame_size(all_cell_num); + func_type = cur_wasm_func->func_type; + all_cell_num = (uint64)cur_func->param_cell_num + + (uint64)cur_func->local_cell_num + + (uint64)cur_wasm_func->max_stack_cell_num + + ((uint64)cur_wasm_func->max_block_num) * sizeof(WASMBranchBlock) / 4; + if (all_cell_num >= UINT32_MAX) { + wasm_runtime_set_exception(self->module_inst, + "WASM interp failed: stack overflow."); + goto got_exception; + } + + frame_size = wasm_interp_interp_frame_size((uint32)all_cell_num); if (!(frame = ALLOC_FRAME(self, frame_size, prev_frame))) { frame = prev_frame; goto got_exception; @@ -2113,19 +2108,18 @@ wasm_interp_call_func_bytecode(WASMThread *self, frame_sp = frame->sp_bottom = frame_lp + cur_func->param_cell_num + cur_func->local_cell_num; - frame->sp_boundary = frame->sp_bottom + cur_func->u.func->max_stack_cell_num; + frame->sp_boundary = frame->sp_bottom + cur_wasm_func->max_stack_cell_num; frame_csp = frame->csp_bottom = (WASMBranchBlock*)frame->sp_boundary; - frame->csp_boundary = frame->csp_bottom + cur_func->u.func->max_block_num; + frame->csp_boundary = frame->csp_bottom + cur_wasm_func->max_block_num; /* Initialize the local varialbes */ memset(frame_lp + cur_func->param_cell_num, 0, - cur_func->local_cell_num * 4); + (uint32)(cur_func->local_cell_num * 4)); /* Push function block as first block */ - func_type = cur_func->u.func->func_type; ret_type = func_type->result_count - ? func_type->types[func_type->param_count] + ? cur_func->param_types[func_type->param_count] : VALUE_TYPE_VOID; PUSH_CSP(BLOCK_TYPE_FUNCTION, ret_type, frame_ip, NULL, frame_ip_end - 1); diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_interp.h b/core/iwasm/runtime/vmcore-wasm/wasm_interp.h index e7a1d779e..47c35cfb5 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_interp.h +++ b/core/iwasm/runtime/vmcore-wasm/wasm_interp.h @@ -55,7 +55,8 @@ typedef struct WASMInterpFrame { static inline unsigned wasm_interp_interp_frame_size(unsigned all_cell_num) { - return align_uint(offsetof(WASMInterpFrame, lp) + all_cell_num * 5, 4); + return align_uint((uint32)offsetof(WASMInterpFrame, lp) + + all_cell_num * 5, 4); } void diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_loader.c b/core/iwasm/runtime/vmcore-wasm/wasm_loader.c index 81144c31b..f3bd51058 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_loader.c +++ b/core/iwasm/runtime/vmcore-wasm/wasm_loader.c @@ -11,6 +11,7 @@ #include "wasm_log.h" #include "wasm_memory.h" #include "wasm_dlfcn.h" +#include "bh_common.h" /* Read a value of given type from the address pointed to by the given pointer and increase the pointer to the position just after the @@ -108,7 +109,7 @@ read_leb(const uint8 *buf, const uint8 *buf_end, error_buf, error_buf_size)) \ return false; \ p += off; \ - res = (uint32)res64; \ + res = (int32)res64; \ } while (0) #define read_leb_uint8(p, p_end, res) do { \ @@ -118,11 +119,11 @@ read_leb(const uint8 *buf, const uint8 *buf_end, error_buf, error_buf_size)) \ return false; \ p += off; \ - res = (uint32)res64; \ + res = (uint8)res64; \ } while (0) static char* -const_str_set_insert(const uint8 *str, int32 len, WASMModule *module, +const_str_set_insert(const uint8 *str, uint32 len, WASMModule *module, char* error_buf, uint32 error_buf_size) { HashMap *set = module->const_str_set; @@ -135,7 +136,7 @@ const_str_set_insert(const uint8 *str, int32 len, WASMModule *module, return NULL; } - memcpy(c_str, str, len); + bh_memcpy_s(c_str, len + 1, str, len); c_str[len] = '\0'; if ((value = wasm_hash_map_find(set, c_str))) { @@ -215,6 +216,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, { const uint8 *p = buf, *p_end = buf_end, *p_org; uint32 type_count, param_count, result_count, i, j; + uint64 total_size; uint8 flag; WASMType *type; @@ -222,13 +224,15 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (type_count) { module->type_count = type_count; - if (!(module->types = wasm_malloc(sizeof(WASMType*) * type_count))) { + total_size = sizeof(WASMType*) * (uint64)type_count; + if (total_size >= UINT32_MAX + || !(module->types = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load type section failed: allocate memory failed."); return false; } - memset(module->types, 0, sizeof(WASMType*) * type_count); + memset(module->types, 0, (uint32)total_size); for (i = 0; i < type_count; i++) { CHECK_BUF(p, p_end, 1); @@ -254,8 +258,10 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, CHECK_BUF(p, p_end, result_count); p = p_org; - if (!(type = module->types[i] = wasm_malloc(offsetof(WASMType, types) + - sizeof(uint8) * (param_count + result_count)))) { + total_size = offsetof(WASMType, types) + + sizeof(uint8) * (uint64)(param_count + result_count); + if (total_size >= UINT32_MAX + || !(type = module->types[i] = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load type section failed: allocate memory failed."); return false; @@ -398,6 +404,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, { const uint8 *p = buf, *p_end = buf_end, *p_old; uint32 import_count, name_len, type_index, i, u32, flags; + uint64 total_size; WASMImport *import; WASMImport *import_functions = NULL, *import_tables = NULL; WASMImport *import_memories = NULL, *import_globals = NULL; @@ -408,13 +415,15 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, if (import_count) { module->import_count = import_count; - if (!(module->imports = wasm_malloc(sizeof(WASMImport) * import_count))) { + total_size = sizeof(WASMImport) * (uint64)import_count; + if (total_size >= UINT32_MAX + || !(module->imports = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load import section failed: allocate memory failed."); return false; } - memset(module->imports, 0, sizeof(WASMImport) * import_count); + memset(module->imports, 0, (uint32)total_size); p_old = p; @@ -514,6 +523,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, read_leb_uint8(p, p_end, kind); switch (kind) { case IMPORT_KIND_FUNC: /* import function */ + wasm_assert(import_functions); import = import_functions++; read_leb_uint32(p, p_end, type_index); if (type_index >= module->type_count) { @@ -543,6 +553,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, break; case IMPORT_KIND_TABLE: /* import table */ + wasm_assert(import_tables); import = import_tables++; if (!load_table_import(&p, p_end, &import->u.table, error_buf, error_buf_size)) @@ -554,6 +565,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, break; case IMPORT_KIND_MEMORY: /* import memory */ + wasm_assert(import_memories); import = import_memories++; if (!load_memory_import(&p, p_end, &import->u.memory, error_buf, error_buf_size)) @@ -565,6 +577,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, break; case IMPORT_KIND_GLOBAL: /* import global */ + wasm_assert(import_globals); import = import_globals++; read_leb_uint8(p, p_end, import->u.global.type); read_leb_uint8(p, p_end, mutable); @@ -590,6 +603,16 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, import->u.names.module_name = module_name; import->u.names.field_name = field_name; } + +#if WASM_ENABLE_WASI != 0 + import = module->import_functions; + for (i = 0; i < module->import_function_count; i++, import++) { + if (!strcmp(import->u.names.module_name, "wasi_unstable")) { + module->is_wasi_module = true; + break; + } + } +#endif } if (p != p_end) { @@ -613,7 +636,8 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, { const uint8 *p = buf, *p_end = buf_end; const uint8 *p_code = buf_code, *p_code_end, *p_code_save; - uint32 func_count, total_size; + uint32 func_count; + uint64 total_size; uint32 code_count = 0, code_size, type_index, i, j, k, local_type_index; uint32 local_count, local_set_count, sub_local_count; uint8 type; @@ -632,13 +656,15 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, if (func_count) { module->function_count = func_count; - if (!(module->functions = wasm_malloc(sizeof(WASMFunction*) * func_count))) { + total_size = sizeof(WASMFunction*) * (uint64)func_count; + if (total_size >= UINT32_MAX + || !(module->functions = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load function section failed: allocate memory failed."); return false; } - memset(module->functions, 0, sizeof(WASMFunction*) * func_count); + memset(module->functions, 0, (uint32)total_size); for (i = 0; i < func_count; i++) { /* Resolve function type */ @@ -678,10 +704,11 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, } /* Alloc memory, layout: function structure + local types */ - code_size = p_code_end - p_code; - total_size = sizeof(WASMFunction) + local_count; + code_size = (uint32)(p_code_end - p_code); - if (!(func = module->functions[i] = wasm_malloc(total_size))) { + total_size = sizeof(WASMFunction) + (uint64)local_count; + if (total_size >= UINT32_MAX + || !(func = module->functions[i] = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load function section failed: " "allocate memory failed."); @@ -689,7 +716,7 @@ load_function_section(const uint8 *buf, const uint8 *buf_end, } /* Set function type, local count, code size and code body */ - memset(func, 0, total_size); + memset(func, 0, (uint32)total_size); func->func_type = module->types[type_index]; func->local_count = local_count; if (local_count > 0) @@ -741,6 +768,7 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, { const uint8 *p = buf, *p_end = buf_end; uint32 table_count, i; + uint64 total_size; WASMTable *table; read_leb_uint32(p, p_end, table_count); @@ -752,14 +780,16 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, return false; } module->table_count = table_count; - if (!(module->tables = wasm_malloc(sizeof(WASMTable) * table_count))) { + total_size = sizeof(WASMTable) * (uint64)table_count; + if (total_size >= UINT32_MAX + || !(module->tables = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load table section failed: " "allocate memory failed."); return false; } - memset(module->tables, 0, sizeof(WASMTable) * table_count); + memset(module->tables, 0, (uint32)total_size); /* load each table */ table = module->tables; @@ -784,6 +814,7 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, { const uint8 *p = buf, *p_end = buf_end; uint32 memory_count, i; + uint64 total_size; WASMMemory *memory; read_leb_uint32(p, p_end, memory_count); @@ -795,14 +826,16 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, return false; } module->memory_count = memory_count; - if (!(module->memories = wasm_malloc(sizeof(WASMMemory) * memory_count))) { + total_size = sizeof(WASMMemory) * (uint64)memory_count; + if (total_size >= UINT32_MAX + || !(module->memories = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load memory section failed: " "allocate memory failed."); return false; } - memset(module->memories, 0, sizeof(WASMMemory) * memory_count); + memset(module->memories, 0, (uint32)total_size); /* load each memory */ memory = module->memories; @@ -827,20 +860,23 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, { const uint8 *p = buf, *p_end = buf_end; uint32 global_count, i; + uint64 total_size; WASMGlobal *global; read_leb_uint32(p, p_end, global_count); if (global_count) { module->global_count = global_count; - if (!(module->globals = wasm_malloc(sizeof(WASMGlobal) * global_count))) { + total_size = sizeof(WASMGlobal) * (uint64)global_count; + if (total_size >= UINT32_MAX + || !(module->globals = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load global section failed: " "allocate memory failed."); return false; } - memset(module->globals, 0, sizeof(WASMGlobal) * global_count); + memset(module->globals, 0, (uint32)total_size); global = module->globals; @@ -872,21 +908,24 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, { const uint8 *p = buf, *p_end = buf_end; uint32 export_count, i, index; - uint8 str_len; + uint64 total_size; + uint32 str_len; WASMExport *export; read_leb_uint32(p, p_end, export_count); if (export_count) { module->export_count = export_count; - if (!(module->exports = wasm_malloc(sizeof(WASMExport) * export_count))) { + total_size = sizeof(WASMExport) * (uint64)export_count; + if (total_size >= UINT32_MAX + || !(module->exports = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load export section failed: " "allocate memory failed."); return false; } - memset(module->exports, 0, sizeof(WASMExport) * export_count); + memset(module->exports, 0, (uint32)total_size); export = module->exports; for (i = 0; i < export_count; i++, export++) { @@ -965,21 +1004,23 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m { const uint8 *p = buf, *p_end = buf_end; uint32 table_segment_count, i, j, table_index, function_count, function_index; + uint64 total_size; WASMTableSeg *table_segment; read_leb_uint32(p, p_end, table_segment_count); if (table_segment_count) { module->table_seg_count = table_segment_count; - if (!(module->table_segments = wasm_malloc - (sizeof(WASMTableSeg) * table_segment_count))) { + total_size = sizeof(WASMTableSeg) * (uint64)table_segment_count; + if (total_size >= UINT32_MAX + || !(module->table_segments = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load table segment section failed: " "allocate memory failed."); return false; } - memset(module->table_segments, 0, sizeof(WASMTableSeg) * table_segment_count); + memset(module->table_segments, 0, (uint32)total_size); table_segment = module->table_segments; for (i = 0; i < table_segment_count; i++, table_segment++) { @@ -993,8 +1034,10 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end, WASMModule *m read_leb_uint32(p, p_end, function_count); table_segment->function_count = function_count; - if (!(table_segment->func_indexes = (uint32 *) - wasm_malloc(sizeof(uint32) * function_count))) { + total_size = sizeof(uint32) * (uint64)function_count; + if (total_size >= UINT32_MAX + || !(table_segment->func_indexes = (uint32 *) + wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load table segment section failed: " "allocate memory failed."); @@ -1025,6 +1068,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, { const uint8 *p = buf, *p_end = buf_end; uint32 data_seg_count, i, mem_index, data_seg_len; + uint64 total_size; WASMDataSeg *dataseg; InitializerExpression init_expr; @@ -1032,15 +1076,16 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, if (data_seg_count) { module->data_seg_count = data_seg_count; - if (!(module->data_segments = - wasm_malloc(sizeof(WASMDataSeg*) * data_seg_count))) { + total_size = sizeof(WASMDataSeg*) * (uint64)data_seg_count; + if (total_size >= UINT32_MAX + || !(module->data_segments = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Load data segment section failed: " "allocate memory failed."); return false; } - memset(module->data_segments, 0, sizeof(WASMDataSeg*) * data_seg_count); + memset(module->data_segments, 0, (uint32)total_size); for (i = 0; i < data_seg_count; i++) { read_leb_uint32(p, p_end, mem_index); @@ -1051,14 +1096,15 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end, read_leb_uint32(p, p_end, data_seg_len); if (!(dataseg = module->data_segments[i] = - wasm_malloc(sizeof(WASMDataSeg)))) { + wasm_malloc((uint32)sizeof(WASMDataSeg)))) { set_error_buf(error_buf, error_buf_size, "Load data segment section failed: " "allocate memory failed."); return false; } - memcpy(&dataseg->base_offset, &init_expr, sizeof(init_expr)); + bh_memcpy_s(&dataseg->base_offset, sizeof(InitializerExpression), + &init_expr, sizeof(InitializerExpression)); dataseg->memory_index = mem_index; dataseg->data_length = data_seg_len; @@ -1343,6 +1389,8 @@ create_sections(const uint8 *buf, uint32 size, uint8 section_type; uint32 section_size; + wasm_assert(!*p_section_list); + p += 8; while (p < p_end) { CHECK_BUF(p, p_end, 1); @@ -1548,6 +1596,25 @@ wasm_loader_unload(WASMModule *module) wasm_free(module); } +#if WASM_ENABLE_WASI != 0 +void +wasm_runtime_set_wasi_args(WASMModule *module, + const char *dir_list[], uint32 dir_count, + const char *map_dir_list[], uint32 map_dir_count, + const char *env_list[], uint32 env_count, + const char *argv[], uint32 argc) +{ + module->wasi_args.dir_list = dir_list; + module->wasi_args.dir_count = dir_count; + module->wasi_args.map_dir_list = map_dir_list; + module->wasi_args.map_dir_count = map_dir_count; + module->wasi_args.env = env_list; + module->wasi_args.env_count = env_count; + module->wasi_args.argv = argv; + module->wasi_args.argc = argc; +} +#endif + #if WASM_ENABLE_HASH_BLOCK_ADDR != 0 typedef struct block_addr { uint8 block_type; @@ -1568,7 +1635,8 @@ wasm_loader_find_block_addr(WASMModule *module, { const uint8 *p = start_addr, *p_end = code_end_addr; uint8 *else_addr = NULL; - uint32 block_nested_depth = 1, count, i, u32, u64; + uint32 block_nested_depth = 1, count, i, u32; + uint64 u64; uint8 opcode, u8; #if WASM_ENABLE_HASH_BLOCK_ADDR != 0 @@ -1586,7 +1654,7 @@ wasm_loader_find_block_addr(WASMModule *module, BlockAddr block_stack[16] = { 0 }, *block; uint32 j, t; - i = ((uintptr_t)start_addr) ^ ((uintptr_t)start_addr >> 16); + i = (uint32)(((uintptr_t)start_addr) ^ ((uintptr_t)start_addr >> 16)); i = i % BLOCK_ADDR_CACHE_SIZE; block = module->block_addr_cache[i]; for (j = 0; j < BLOCK_ADDR_CONFLICT_SIZE; j++) { @@ -1613,7 +1681,7 @@ wasm_loader_find_block_addr(WASMModule *module, case WASM_OP_BLOCK: case WASM_OP_LOOP: case WASM_OP_IF: - read_leb_uint32(p, p_end, u32); /* blocktype */ + read_leb_uint8(p, p_end, u8); /* blocktype */ #if WASM_ENABLE_HASH_BLOCK_ADDR == 0 if (block_nested_depth < sizeof(block_stack)/sizeof(BlockAddr)) { block_stack[block_nested_depth].start_addr = p; @@ -1658,7 +1726,7 @@ wasm_loader_find_block_addr(WASMModule *module, for (t = 0; t < sizeof(block_stack)/sizeof(BlockAddr); t++) { start_addr = block_stack[t].start_addr; if (start_addr) { - i = ((uintptr_t)start_addr) ^ ((uintptr_t)start_addr >> 16); + i = (uint32)(((uintptr_t)start_addr) ^ ((uintptr_t)start_addr >> 16)); i = i % BLOCK_ADDR_CACHE_SIZE; block = module->block_addr_cache[i]; for (j = 0; j < BLOCK_ADDR_CONFLICT_SIZE; j++) @@ -1937,7 +2005,7 @@ memory_realloc(void *mem_old, uint32 size_old, uint32 size_new) uint8 *mem_new; wasm_assert(size_new > size_old); if ((mem_new = wasm_malloc(size_new))) { - memcpy(mem_new, mem_old, size_old); + bh_memcpy_s(mem_new, size_new, mem_old, size_old); memset(mem_new + size_old, 0, size_new - size_old); wasm_free(mem_old); } @@ -2171,8 +2239,9 @@ pop_type(uint8 type, uint8 **p_frame_ref, uint32 *p_stack_cell_num, #define CHECK_CSP_PUSH() do { \ if (frame_csp >= frame_csp_boundary) { \ MEM_REALLOC(frame_csp_bottom, frame_csp_size, \ - frame_csp_size + 8 * sizeof(BranchBlock));\ - frame_csp_size += 8 * sizeof(BranchBlock); \ + (uint32)(frame_csp_size \ + + 8 * sizeof(BranchBlock))); \ + frame_csp_size += (uint32)(8 * sizeof(BranchBlock)); \ frame_csp_boundary = frame_csp_bottom + \ frame_csp_size / sizeof(BranchBlock); \ frame_csp = frame_csp_bottom + csp_num; \ @@ -2281,10 +2350,10 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, uint32 stack_cell_num = 0, csp_num = 0; uint32 frame_ref_size, frame_csp_size; uint8 *param_types, ret_type, *local_types, local_type, global_type; - uint32 count, i, local_idx, global_idx, block_return_type, depth, u32; + uint32 count, i, local_idx, global_idx, depth, u32; int32 i32, i32_const = 0; int64 i64; - uint8 opcode, u8; + uint8 opcode, u8, block_return_type; bool return_value = false, is_i32_const = false; global_count = module->import_global_count + module->global_count; @@ -2332,18 +2401,18 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, break; case WASM_OP_BLOCK: - read_leb_uint32(p, p_end, block_return_type); + read_leb_uint8(p, p_end, block_return_type); PUSH_CSP(BLOCK_TYPE_BLOCK, block_return_type, p); break; case WASM_OP_LOOP: - read_leb_uint32(p, p_end, block_return_type); + read_leb_uint8(p, p_end, block_return_type); PUSH_CSP(BLOCK_TYPE_LOOP, block_return_type, p); break; case WASM_OP_IF: POP_I32(); - read_leb_uint32(p, p_end, block_return_type); + read_leb_uint8(p, p_end, block_return_type); PUSH_CSP(BLOCK_TYPE_IF, block_return_type, p); if (!is_i32_const) (frame_csp - 1)->jumped_by_br = true; @@ -2535,8 +2604,10 @@ handle_op_br: func_type = module->functions[func_idx - module->import_function_count]->func_type; - for (idx = func_type->param_count - 1; idx >= 0; idx--) - POP_TYPE(func_type->types[idx]); + if (func_type->param_count > 0) { + for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) + POP_TYPE(func_type->types[idx]); + } if (func_type->result_count) PUSH_TYPE(func_type->types[func_type->param_count]); @@ -2575,8 +2646,10 @@ handle_op_br: func_type = module->types[type_idx]; - for (idx = func_type->param_count - 1; idx >= 0; idx--) - POP_TYPE(func_type->types[idx]); + if (func_type->param_count > 0) { + for (idx = (int32)(func_type->param_count - 1); idx >= 0; idx--) + POP_TYPE(func_type->types[idx]); + } PUSH_TYPE(func_type->types[func_type->param_count]); break; diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c index f6f4ef038..aaf6362c0 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c +++ b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c @@ -12,6 +12,7 @@ #include "wasm_platform_log.h" #include "wasm_memory.h" #include "mem_alloc.h" +#include "bh_common.h" static void @@ -77,9 +78,9 @@ wasm_runtime_call_wasm(WASMModuleInstance *module_inst, uint32 stack_size; /* Set to 8 bytes align */ - stack = (stack + 7) & ~7; - stack_size = exec_env->stack_size - - (stack - (uintptr_t)exec_env->stack); + stack = (stack + 7) & (uintptr_t)~7; + stack_size = (uint32)(exec_env->stack_size + - (stack - (uintptr_t)exec_env->stack)); if (!exec_env->stack || exec_env->stack_size <= 0 || exec_env->stack_size < stack - (uintptr_t)exec_env->stack) { @@ -171,18 +172,19 @@ memory_instantiate(uint32 init_page_count, uint32 max_page_count, char *error_buf, uint32 error_buf_size) { WASMMemoryInstance *memory; - uint32 total_size = offsetof(WASMMemoryInstance, base_addr) + - NumBytesPerPage * init_page_count + + uint64 total_size = offsetof(WASMMemoryInstance, base_addr) + + NumBytesPerPage * (uint64)init_page_count + addr_data_size + global_data_size; /* Allocate memory space, addr data and global data */ - if (!(memory = wasm_malloc(total_size))) { + if (total_size >= UINT32_MAX + || !(memory = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate memory failed: allocate memory failed."); return NULL; } - memset(memory, 0, total_size); + memset(memory, 0, (uint32)total_size); memory->cur_page_count = init_page_count; memory->max_page_count = max_page_count; @@ -238,23 +240,23 @@ memories_instantiate(const WASMModule *module, uint32 addr_data_size, WASMImport *import; uint32 mem_index = 0, i, memory_count = module->import_memory_count + module->memory_count; - uint32 total_size; + uint64 total_size; WASMMemoryInstance **memories, *memory; if (memory_count == 0 && global_data_size > 0) memory_count = 1; - total_size = sizeof(WASMMemoryInstance*) * memory_count; - memories = wasm_malloc(total_size); + total_size = sizeof(WASMMemoryInstance*) * (uint64)memory_count; - if (!memories) { + if (total_size >= UINT32_MAX + || !(memories = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate memory failed: " "allocate memory failed."); return NULL; } - memset(memories, 0, total_size); + memset(memories, 0, (uint32)total_size); /* instantiate memories from import section */ import = module->import_memories; @@ -329,24 +331,26 @@ tables_instantiate(const WASMModule *module, WASMImport *import; uint32 table_index = 0, i, table_count = module->import_table_count + module->table_count; - uint32 total_size = sizeof(WASMTableInstance*) * table_count; - WASMTableInstance **tables = wasm_malloc(total_size), *table; + uint64 total_size = sizeof(WASMTableInstance*) * (uint64)table_count; + WASMTableInstance **tables, *table; - if (!tables) { + if (total_size >= UINT32_MAX + || !(tables = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate table failed: " "allocate memory failed."); return NULL; } - memset(tables, 0, total_size); + memset(tables, 0, (uint32)total_size); /* instantiate tables from import section */ import = module->import_tables; for (i = 0; i < module->import_table_count; i++, import++) { total_size = offsetof(WASMTableInstance, base_addr) + - sizeof(uint32) * import->u.table.init_size; - if (!(table = tables[table_index++] = wasm_malloc(total_size))) { + sizeof(uint32) * (uint64)import->u.table.init_size; + if (total_size >= UINT32_MAX + || !(table = tables[table_index++] = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate table failed: " "allocate memory failed."); @@ -354,7 +358,7 @@ tables_instantiate(const WASMModule *module, return NULL; } - memset(table, 0, total_size); + memset(table, 0, (uint32)total_size); table->cur_size = import->u.table.init_size; table->max_size = import->u.table.max_size; } @@ -362,8 +366,9 @@ tables_instantiate(const WASMModule *module, /* instantiate tables from table section */ for (i = 0; i < module->table_count; i++) { total_size = offsetof(WASMTableInstance, base_addr) + - sizeof(uint32) * module->tables[i].init_size; - if (!(table = tables[table_index++] = wasm_malloc(total_size))) { + sizeof(uint32) * (uint64)module->tables[i].init_size; + if (total_size >= UINT32_MAX + || !(table = tables[table_index++] = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate table failed: " "allocate memory failed."); @@ -371,7 +376,7 @@ tables_instantiate(const WASMModule *module, return NULL; } - memset(table, 0, total_size); + memset(table, 0, (uint32)total_size); table->cur_size = module->tables[i].init_size; table->max_size = module->tables[i].max_size; } @@ -399,24 +404,26 @@ functions_deinstantiate(WASMFunctionInstance *functions, uint32 count) static bool function_init_local_offsets(WASMFunctionInstance *func) { - uint16 local_offset = 0; + uint32 local_offset = 0; WASMType *param_type = func->u.func->func_type; uint32 param_count = param_type->param_count; uint8 *param_types = param_type->types; uint32 local_count = func->u.func->local_count; uint8 *local_types = func->u.func->local_types; - uint32 i, total_size = (param_count + local_count) * sizeof(uint16); + uint32 i; + uint64 total_size = sizeof(uint16) * (uint64)(param_count + local_count); - if (!(func->local_offsets = wasm_malloc(total_size))) + if (total_size >= UINT32_MAX + || !(func->local_offsets = wasm_malloc((uint32)total_size))) return false; for (i = 0; i < param_count; i++) { - func->local_offsets[i] = local_offset; + func->local_offsets[i] = (uint16)local_offset; local_offset += wasm_value_type_cell_num(param_types[i]); } for (i = 0; i < local_count; i++) { - func->local_offsets[param_count + i] = local_offset; + func->local_offsets[param_count + i] = (uint16)local_offset; local_offset += wasm_value_type_cell_num(local_types[i]); } @@ -434,17 +441,18 @@ functions_instantiate(const WASMModule *module, WASMImport *import; uint32 i, function_count = module->import_function_count + module->function_count; - uint32 total_size = sizeof(WASMFunctionInstance) * function_count; - WASMFunctionInstance *functions = wasm_malloc(total_size), *function; + uint64 total_size = sizeof(WASMFunctionInstance) * (uint64)function_count; + WASMFunctionInstance *functions, *function; - if (!functions) { + if (total_size >= UINT32_MAX + || !(functions = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate function failed: " "allocate memory failed."); return NULL; } - memset(functions, 0, total_size); + memset(functions, 0, (uint32)total_size); /* instantiate functions from import section */ function = functions; @@ -459,6 +467,12 @@ functions_instantiate(const WASMModule *module, wasm_type_return_cell_num(import->u.function.func_type); function->local_cell_num = 0; + function->param_count = + (uint16)function->u.func_import->func_type->param_count; + function->local_count = 0; + function->param_types = function->u.func_import->func_type->types; + function->local_types = NULL; + function++; } @@ -475,6 +489,11 @@ functions_instantiate(const WASMModule *module, wasm_get_cell_num(function->u.func->local_types, function->u.func->local_count); + function->param_count = (uint16)function->u.func->func_type->param_count; + function->local_count = (uint16)function->u.func->local_count; + function->param_types = function->u.func->func_type->types; + function->local_types = function->u.func->local_types; + if (!function_init_local_offsets(function)) { functions_deinstantiate(functions, function_count); return NULL; @@ -510,17 +529,18 @@ globals_instantiate(const WASMModule *module, uint32 addr_data_offset = 0, global_data_offset = 0; uint32 i, global_count = module->import_global_count + module->global_count; - uint32 total_size = sizeof(WASMGlobalInstance) * global_count; - WASMGlobalInstance *globals = wasm_malloc(total_size), *global; + uint64 total_size = sizeof(WASMGlobalInstance) * (uint64)global_count; + WASMGlobalInstance *globals, *global; - if (!globals) { + if (total_size >= UINT32_MAX + || !(globals = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate global failed: " "allocate memory failed."); return NULL; } - memset(globals, 0, total_size); + memset(globals, 0, (uint32)total_size); /* instantiate globals from import section */ global = globals; @@ -535,7 +555,7 @@ globals_instantiate(const WASMModule *module, global_data_offset += wasm_value_type_size(global->type); if (global->is_addr) - addr_data_offset += sizeof(uint32); + addr_data_offset += (uint32)sizeof(uint32); global++; } @@ -550,7 +570,7 @@ globals_instantiate(const WASMModule *module, global_data_offset += wasm_value_type_size(global->type); if (global->is_addr) - addr_data_offset += sizeof(uint32); + addr_data_offset += (uint32)sizeof(uint32); global++; } @@ -583,7 +603,7 @@ globals_instantiate_fix(WASMGlobalInstance *globals, } else if (!strcmp(import->u.names.field_name, "DYNAMICTOP_PTR")) { global->initial_value.i32 = - NumBytesPerPage * module_inst->default_memory->cur_page_count; + (int32)(NumBytesPerPage * module_inst->default_memory->cur_page_count); module_inst->DYNAMICTOP_PTR_offset = global->data_offset; } else if (!strcmp(import->u.names.field_name, "STACKTOP")) { @@ -604,7 +624,8 @@ globals_instantiate_fix(WASMGlobalInstance *globals, global->initial_value = globals[init_expr->u.global_index].initial_value; } else { - memcpy(&global->initial_value, &init_expr->u, sizeof(int64)); + bh_memcpy_s(&global->initial_value, sizeof(WASMValue), + &init_expr->u, sizeof(init_expr->u)); } global++; } @@ -647,16 +668,18 @@ export_functions_instantiate(const WASMModule *module, { WASMExportFuncInstance *export_funcs, *export_func; WASMExport *export = module->exports; - uint32 i, total_size = sizeof(WASMExportFuncInstance) * export_func_count; + uint32 i; + uint64 total_size = sizeof(WASMExportFuncInstance) * (uint64)export_func_count; - if (!(export_func = export_funcs = wasm_malloc(total_size))) { + if (total_size >= UINT32_MAX + || !(export_func = export_funcs = wasm_malloc((uint32)total_size))) { set_error_buf(error_buf, error_buf_size, "Instantiate export function failed: " "allocate memory failed."); return NULL; } - memset(export_funcs, 0, total_size); + memset(export_funcs, 0, (uint32)total_size); for (i = 0; i < module->export_count; i++, export++) if (export->kind == EXPORT_KIND_FUNC) { @@ -710,11 +733,209 @@ execute_start_function(WASMModuleInstance *module_inst) return true; wasm_assert(!func->is_import_func && func->param_cell_num == 0 - && func->ret_cell_num == 0); + && func->ret_cell_num == 0); return wasm_runtime_call_wasm(module_inst, NULL, func, 0, NULL); } +#if WASM_ENABLE_WASI != 0 +static bool +wasm_runtime_init_wasi(WASMModuleInstance *module_inst, + const char *dir_list[], uint32 dir_count, + const char *map_dir_list[], uint32 map_dir_count, + const char *env[], uint32 env_count, + const char *argv[], uint32 argc, + char *error_buf, uint32 error_buf_size) +{ + size_t *argv_offsets = NULL; + char *argv_buf = NULL; + size_t *env_offsets = NULL; + char *env_buf = NULL; + uint64 argv_buf_len = 0, env_buf_len = 0; + uint32 argv_buf_offset = 0, env_buf_offset = 0; + struct fd_table *curfds; + struct fd_prestats *prestats; + struct argv_environ_values *argv_environ; + int32 offset_argv_offsets = 0, offset_env_offsets = 0; + int32 offset_argv_buf = 0, offset_env_buf = 0; + int32 offset_curfds = 0; + int32 offset_prestats = 0; + int32 offset_argv_environ = 0; + __wasi_fd_t wasm_fd = 3; + int32 raw_fd; + char *path, resolved_path[PATH_MAX]; + uint64 total_size; + uint32 i; + + if (!module_inst->default_memory) { + argv_environ = module_inst->wasi_ctx.argv_environ = NULL; + prestats = module_inst->wasi_ctx.prestats = NULL; + curfds = module_inst->wasi_ctx.curfds = NULL; + + return true; + } + + /* process argv[0], trip the path and suffix, only keep the program name */ + for (i = 0; i < argc; i++) + argv_buf_len += strlen(argv[i]) + 1; + + total_size = sizeof(size_t) * (uint64)argc; + if (total_size >= UINT32_MAX + || !(offset_argv_offsets = wasm_runtime_module_malloc + (module_inst, (uint32)total_size)) + || argv_buf_len >= UINT32_MAX + || !(offset_argv_buf = wasm_runtime_module_malloc + (module_inst, (uint32)argv_buf_len))) { + set_error_buf(error_buf, error_buf_size, + "Init wasi environment failed: allocate memory failed."); + goto fail; + } + + argv_offsets = (size_t*) + wasm_runtime_addr_app_to_native(module_inst, offset_argv_offsets); + argv_buf = (char*) + wasm_runtime_addr_app_to_native(module_inst, offset_argv_buf); + + for (i = 0; i < argc; i++) { + argv_offsets[i] = argv_buf_offset; + bh_strcpy_s(argv_buf + argv_buf_offset, + (uint32)argv_buf_len - argv_buf_offset, argv[i]); + argv_buf_offset += (uint32)(strlen(argv[i]) + 1); + } + + for (i = 0; i < env_count; i++) + env_buf_len += strlen(env[i]) + 1; + + total_size = sizeof(size_t) * (uint64)argc; + if (total_size >= UINT32_MAX + || !(offset_env_offsets = wasm_runtime_module_malloc + (module_inst, (uint32)total_size)) + || env_buf_len >= UINT32_MAX + || !(offset_env_buf = wasm_runtime_module_malloc + (module_inst, (uint32)env_buf_len))) { + set_error_buf(error_buf, error_buf_size, + "Init wasi environment failed: allocate memory failed."); + goto fail; + } + + env_offsets = (size_t*) + wasm_runtime_addr_app_to_native(module_inst, offset_env_offsets); + env_buf = (char*) + wasm_runtime_addr_app_to_native(module_inst, offset_env_buf); + + for (i = 0; i < env_count; i++) { + env_offsets[i] = env_buf_offset; + bh_strcpy_s(env_buf + env_buf_offset, + (uint32)env_buf_len - env_buf_offset, env[i]); + env_buf_offset += (uint32)(strlen(env[i]) + 1); + } + + if (!(offset_curfds = wasm_runtime_module_malloc + (module_inst, sizeof(struct fd_table))) + || !(offset_prestats = wasm_runtime_module_malloc + (module_inst, sizeof(struct fd_prestats))) + || !(offset_argv_environ = wasm_runtime_module_malloc + (module_inst, sizeof(struct argv_environ_values)))) { + set_error_buf(error_buf, error_buf_size, + "Init wasi environment failed: allocate memory failed."); + goto fail; + } + + curfds = module_inst->wasi_ctx.curfds = (struct fd_table*) + wasm_runtime_addr_app_to_native(module_inst, offset_curfds); + prestats = module_inst->wasi_ctx.prestats = (struct fd_prestats*) + wasm_runtime_addr_app_to_native(module_inst, offset_prestats); + argv_environ = module_inst->wasi_ctx.argv_environ = + (struct argv_environ_values*)wasm_runtime_addr_app_to_native + (module_inst, offset_argv_environ); + + fd_table_init(curfds); + fd_prestats_init(prestats); + + if (!argv_environ_init(argv_environ, + argv_offsets, argc, + argv_buf, argv_buf_len, + env_offsets, env_count, + env_buf, env_buf_len)) { + set_error_buf(error_buf, error_buf_size, + "Init wasi environment failed: " + "init argument environment failed."); + goto fail; + } + + /* Prepopulate curfds with stdin, stdout, and stderr file descriptors. */ + if (!fd_table_insert_existing(curfds, 0, 0) + || !fd_table_insert_existing(curfds, 1, 1) + || !fd_table_insert_existing(curfds, 2, 2)) { + set_error_buf(error_buf, error_buf_size, + "Init wasi environment failed: init fd table failed."); + goto fail; + } + + wasm_fd = 3; + for (i = 0; i < dir_count; i++, wasm_fd++) { + path = realpath(dir_list[i], resolved_path); + if (!path) { + if (error_buf) + snprintf(error_buf, error_buf_size, + "error while pre-opening directory %s: %d\n", + dir_list[i], errno); + goto fail; + } + + raw_fd = open(path, O_RDONLY | O_DIRECTORY, 0); + if (raw_fd == -1) { + if (error_buf) + snprintf(error_buf, error_buf_size, + "error while pre-opening directory %s: %d\n", + dir_list[i], errno); + goto fail; + } + + fd_table_insert_existing(curfds, wasm_fd, raw_fd); + fd_prestats_insert(prestats, dir_list[i], wasm_fd); + } + + return true; + +fail: + if (offset_curfds != 0) + wasm_runtime_module_free(module_inst, offset_curfds); + if (offset_prestats != 0) + wasm_runtime_module_free(module_inst, offset_prestats); + if (offset_argv_environ != 0) + wasm_runtime_module_free(module_inst, offset_argv_environ); + if (offset_argv_buf) + wasm_runtime_module_free(module_inst, offset_argv_buf); + if (offset_argv_offsets) + wasm_runtime_module_free(module_inst, offset_argv_offsets); + if (offset_env_buf) + wasm_runtime_module_free(module_inst, offset_env_buf); + if (offset_env_offsets) + wasm_runtime_module_free(module_inst, offset_env_offsets); + return false; +} + +static void +wasm_runtime_destroy_wasi(WASMModuleInstance *module_inst) +{ + WASIContext *wasi_ctx = &module_inst->wasi_ctx; + + if (wasi_ctx->argv_environ) + argv_environ_destroy(wasi_ctx->argv_environ); + if (wasi_ctx->curfds) + fd_table_destroy(wasi_ctx->curfds); + if (wasi_ctx->prestats) + fd_prestats_destroy(wasi_ctx->prestats); +} + +WASIContext * +wasm_runtime_get_wasi_ctx(WASMModuleInstance *module_inst) +{ + return &module_inst->wasi_ctx; +} +#endif + /** * Instantiate module */ @@ -754,14 +975,14 @@ wasm_runtime_instantiate(WASMModule *module, return NULL; /* Allocate the memory */ - if (!(module_inst = wasm_malloc(sizeof(WASMModuleInstance)))) { + if (!(module_inst = wasm_malloc((uint32)sizeof(WASMModuleInstance)))) { set_error_buf(error_buf, error_buf_size, "Instantiate module failed: allocate memory failed."); globals_deinstantiate(globals); return NULL; } - memset(module_inst, 0, sizeof(WASMModuleInstance)); + memset(module_inst, 0, (uint32)sizeof(WASMModuleInstance)); module_inst->global_count = global_count; module_inst->globals = globals; @@ -818,7 +1039,7 @@ wasm_runtime_instantiate(WASMModule *module, else { *(int32*)addr_data = global->initial_value.i32; /* Store the offset to memory data for global of addr */ - *(int32*)global_data = addr_data - memory_data; + *(int32*)global_data = (int32)(addr_data - memory_data); addr_data += sizeof(int32); } global_data += sizeof(int32); @@ -826,7 +1047,8 @@ wasm_runtime_instantiate(WASMModule *module, case VALUE_TYPE_I64: case VALUE_TYPE_F64: wasm_assert(!global->is_addr); - memcpy(global_data, &global->initial_value.i64, sizeof(int64)); + bh_memcpy_s(global_data, (uint32)(global_data_end - global_data), + &global->initial_value.i64, sizeof(int64)); global_data += sizeof(int64); break; default: @@ -880,7 +1102,8 @@ wasm_runtime_instantiate(WASMModule *module, return NULL; } - memcpy(memory_data + base_offset, data_seg->data, length); + bh_memcpy_s(memory_data + base_offset, memory_size - base_offset, + data_seg->data, length); } } } @@ -909,10 +1132,10 @@ wasm_runtime_instantiate(WASMModule *module, if ((uint32)table_seg->base_offset.u.i32 < module_inst->default_table->cur_size) { length = table_seg->function_count; - if (table_seg->base_offset.u.i32 + length > + if ((uint32)table_seg->base_offset.u.i32 + length > module_inst->default_table->cur_size) length = module_inst->default_table->cur_size - - table_seg->base_offset.u.i32; + - (uint32)table_seg->base_offset.u.i32; /* Check function index */ for (j = 0; j < length; j++) { if (table_seg->func_indexes[j] >= module_inst->function_count) { @@ -922,12 +1145,31 @@ wasm_runtime_instantiate(WASMModule *module, return NULL; } } - memcpy(table_data + table_seg->base_offset.u.i32, - table_seg->func_indexes, length * sizeof(uint32)); + bh_memcpy_s(table_data + table_seg->base_offset.u.i32, + (uint32)((module_inst->default_table->cur_size + - (uint32)table_seg->base_offset.u.i32) + * sizeof(uint32)), + table_seg->func_indexes, (uint32)(length * sizeof(uint32))); } } } +#if WASM_ENABLE_WASI != 0 + if (!wasm_runtime_init_wasi(module_inst, + module->wasi_args.dir_list, + module->wasi_args.dir_count, + module->wasi_args.map_dir_list, + module->wasi_args.map_dir_count, + module->wasi_args.env, + module->wasi_args.env_count, + module->wasi_args.argv, + module->wasi_args.argc, + error_buf, error_buf_size)) { + wasm_runtime_deinstantiate(module_inst); + return NULL; + } +#endif + if (module->start_function != (uint32)-1) { wasm_assert(module->start_function >= module->import_function_count); module_inst->start_function = @@ -968,6 +1210,10 @@ wasm_runtime_deinstantiate(WASMModuleInstance *module_inst) if (!module_inst) return; +#if WASM_ENABLE_WASI != 0 + wasm_runtime_destroy_wasi(module_inst); +#endif + if (module_inst->memory_count > 0) memories_deinstantiate(module_inst->memories, module_inst->memory_count); else if (module_inst->memories != NULL && module_inst->global_count > 0) @@ -1018,15 +1264,15 @@ wasm_runtime_set_ext_memory(WASMModuleInstance *module_inst, #endif bool -wasm_runtime_enlarge_memory(WASMModuleInstance *module, int inc_page_count) +wasm_runtime_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) { #if WASM_ENABLE_MEMORY_GROW != 0 WASMMemoryInstance *memory = module->default_memory; WASMMemoryInstance *new_memory; uint32 total_page_count = inc_page_count + memory->cur_page_count; - uint32 total_size = offsetof(WASMMemoryInstance, base_addr) + + uint64 total_size = offsetof(WASMMemoryInstance, base_addr) + memory->addr_data_size + - NumBytesPerPage * total_page_count + + NumBytesPerPage * (uint64)total_page_count + memory->global_data_size; if (inc_page_count <= 0) @@ -1039,7 +1285,8 @@ wasm_runtime_enlarge_memory(WASMModuleInstance *module, int inc_page_count) return false; } - if (!(new_memory = wasm_malloc(total_size))) { + if (total_size >= UINT32_MAX + || !(new_memory = wasm_malloc((uint32)total_size))) { wasm_runtime_set_exception(module, "fail to enlarge memory."); return false; } @@ -1059,11 +1306,13 @@ wasm_runtime_enlarge_memory(WASMModuleInstance *module, int inc_page_count) new_memory->end_addr = new_memory->global_data + memory->global_data_size; /* Copy addr data and memory data */ - memcpy(new_memory->addr_data, memory->addr_data, - memory->global_data - memory->addr_data); + bh_memcpy_s(new_memory->addr_data, + (uint32)(memory->global_data - memory->addr_data), + memory->addr_data, + (uint32)(memory->global_data - memory->addr_data)); /* Copy global data */ - memcpy(new_memory->global_data, memory->global_data, - memory->global_data_size); + bh_memcpy_s(new_memory->global_data, new_memory->global_data_size, + memory->global_data, memory->global_data_size); /* Init free space of new memory */ memset(new_memory->memory_data + NumBytesPerPage * memory->cur_page_count, 0, NumBytesPerPage * (total_page_count - memory->cur_page_count)); @@ -1097,7 +1346,7 @@ get_package_type(const uint8 *buf, uint32 size) WASMExecEnv* wasm_runtime_create_exec_env(uint32 stack_size) { - WASMExecEnv *exec_env = wasm_malloc(sizeof(WASMExecEnv)); + WASMExecEnv *exec_env = wasm_malloc((uint32)sizeof(WASMExecEnv)); if (exec_env) { if (!(exec_env->stack = wasm_malloc(stack_size))) { wasm_free(exec_env); @@ -1139,7 +1388,7 @@ wasm_runtime_module_malloc(WASMModuleInstance *module_inst, uint32 size) wasm_runtime_set_exception(module_inst, "out of memory"); return 0; } - return memory->heap_base_offset + (addr - memory->heap_data); + return memory->heap_base_offset + (int32)(addr - memory->heap_data); } void @@ -1161,7 +1410,7 @@ wasm_runtime_module_dup_data(WASMModuleInstance *module_inst, if (buffer_offset != 0) { char *buffer; buffer = wasm_runtime_addr_app_to_native(module_inst, buffer_offset); - memcpy(buffer, src, size); + bh_memcpy_s(buffer, size, src, size); } return buffer_offset; } @@ -1174,7 +1423,7 @@ wasm_runtime_validate_app_addr(WASMModuleInstance *module_inst, uint8 *addr; /* integer overflow check */ - if(app_offset + size < app_offset) { + if(app_offset + (int32)size < app_offset) { goto fail; } @@ -1294,11 +1543,11 @@ wasm_runtime_addr_native_to_app(WASMModuleInstance *module_inst, WASMMemoryInstance *memory = module_inst->default_memory; if (memory->base_addr <= (uint8*)native_ptr && (uint8*)native_ptr < memory->end_addr) - return (uint8*)native_ptr - memory->memory_data; + return (int32)((uint8*)native_ptr - memory->memory_data); else if (memory->heap_data <= (uint8*)native_ptr && (uint8*)native_ptr < memory->heap_data_end) return memory->heap_base_offset - + ((uint8*)native_ptr - memory->heap_data); + + (int32)((uint8*)native_ptr - memory->heap_data); #if WASM_ENABLE_EXT_MEMORY_SPACE != 0 else if (module_inst->ext_mem_data && module_inst->ext_mem_data <= (uint8*)native_ptr @@ -1321,14 +1570,14 @@ wasm_runtime_get_app_addr_range(WASMModuleInstance *module_inst, if (0 <= app_offset && app_offset < memory->heap_base_offset) { app_start_offset = 0; - app_end_offset = NumBytesPerPage * memory->cur_page_count; + app_end_offset = (int32)(NumBytesPerPage * memory->cur_page_count); } else if (memory->heap_base_offset < app_offset && app_offset < memory->heap_base_offset + (memory->heap_data_end - memory->heap_data)) { app_start_offset = memory->heap_base_offset; app_end_offset = memory->heap_base_offset - + (memory->heap_data_end - memory->heap_data); + + (int32)(memory->heap_data_end - memory->heap_data); } #if WASM_ENABLE_EXT_MEMORY_SPACE != 0 else if (module_inst->ext_mem_data @@ -1479,7 +1728,7 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, #endif if (argc1 > sizeof(argv_buf) / sizeof(uint32)) { - size = ((uint64)sizeof(uint32)) * argc1; + size = sizeof(uint32) * (uint64)argc1; if (size >= UINT_MAX || !(argv1 = wasm_malloc((uint32)size))) { wasm_runtime_set_exception(module_inst, "allocate memory failed."); @@ -1524,7 +1773,7 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, else { switch (func_type->types[func_type->param_count]) { case VALUE_TYPE_I32: - ret[0] = invokeNative_Int32(func_ptr, argv1, argc1); + ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, argc1); break; case VALUE_TYPE_I64: PUT_I64_TO_ADDR(ret, invokeNative_Int64(func_ptr, argv1, argc1)); @@ -1587,9 +1836,9 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, argc1 = 1 + MAX_REG_FLOATS + func_type->param_count + 2; if (argc1 > sizeof(argv_buf) / sizeof(uint64)) { - size = sizeof(uint64) * argc1; + size = sizeof(uint64) * (uint64)argc1; if (size >= UINT32_MAX - || !(argv1 = wasm_malloc(size))) { + || !(argv1 = wasm_malloc((uint32)size))) { wasm_runtime_set_exception(module_inst, "allocate memory failed."); return false; } @@ -1641,7 +1890,7 @@ wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, else { switch (func_type->types[func_type->param_count]) { case VALUE_TYPE_I32: - ret[0] = invokeNative_Int32(func_ptr, argv1, n_stacks); + ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks); break; case VALUE_TYPE_I64: PUT_I64_TO_ADDR(ret, invokeNative_Int64(func_ptr, argv1, n_stacks)); diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.h b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.h index 47cc201ea..7e990cd2f 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.h +++ b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.h @@ -9,6 +9,10 @@ #include "wasm.h" #include "wasm_thread.h" #include "wasm_hashmap.h" +#if WASM_ENABLE_WASI != 0 +#include "wasmtime_ssp.h" +#include "posix.h" +#endif #ifdef __cplusplus extern "C" { @@ -81,6 +85,10 @@ typedef struct WASMGlobalInstance { typedef struct WASMFunctionInstance { /* whether it is import function or WASM function */ bool is_import_func; + /* parameter count */ + uint16 param_count; + /* local variable count, 0 for import function */ + uint16 local_count; /* cell num of parameters */ uint16 param_cell_num; /* cell num of return type */ @@ -88,6 +96,10 @@ typedef struct WASMFunctionInstance { /* cell num of local variables, 0 for import function */ uint16 local_cell_num; uint16 *local_offsets; + /* parameter types */ + uint8 *param_types; + /* local types, NULL for import function */ + uint8 *local_types; union { WASMFunctionImport *func_import; WASMFunction *func; @@ -106,6 +118,14 @@ typedef enum { Package_Type_Unknown = 0xFFFF } PackageType; +#if WASM_ENABLE_WASI != 0 +typedef struct WASIContext { + struct fd_table *curfds; + struct fd_prestats *prestats; + struct argv_environ_values *argv_environ; +} WASIContext; +#endif + typedef struct WASMModuleInstance { /* Module instance type, for module instance loaded from WASM bytecode binary, this field is Wasm_Module_Bytecode; @@ -133,6 +153,10 @@ typedef struct WASMModuleInstance { WASMModule *module; +#if WASM_ENABLE_WASI != 0 + WASIContext wasi_ctx; +#endif + uint32 DYNAMICTOP_PTR_offset; uint32 temp_ret; uint32 llvm_stack; @@ -271,7 +295,7 @@ wasm_runtime_get_exception(WASMModuleInstance *module); * @return return true if enlarge successfully, false otherwise */ bool -wasm_runtime_enlarge_memory(WASMModuleInstance *module, int inc_page_count); +wasm_runtime_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count); /* See wasm_export.h for description */ WASMModuleInstance * diff --git a/core/iwasm/runtime/wasmtime-wasi-c/LICENSE b/core/iwasm/runtime/wasmtime-wasi-c/LICENSE new file mode 100644 index 000000000..f9d81955f --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/LICENSE @@ -0,0 +1,220 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +--- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/LICENSE b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/LICENSE new file mode 100644 index 000000000..83386f80a --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/LICENSE @@ -0,0 +1,7 @@ +Please see the LICENSE file in each top-level directory for the terms applicable to that directory and its relative sub-directories. + +The relevant directories and licenses are: + +src/ - BSD-2-Clause; see src/LICENSE for details +include/ - CC0 1.0 Universal (CC0 1.0) Public Domain Dedication +polyfill/clang/ - MIT; see the header of polyfill/clang/stdatomic.h for details diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/include/LICENSE b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/include/LICENSE new file mode 100644 index 000000000..0e259d42c --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/include/LICENSE @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/include/wasmtime_ssp.h b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/include/wasmtime_ssp.h new file mode 100644 index 000000000..6a0d348c4 --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/include/wasmtime_ssp.h @@ -0,0 +1,866 @@ +/* + * Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. + * See https://github.com/CraneStation/wasmtime/blob/master/LICENSE for license information. + * + * This file declares an interface similar to WASI, but augmented to expose + * some implementation details such as the curfds arguments that we pass + * around to avoid storing them in TLS. + */ + +#ifndef WASMTIME_SSP_H +#define WASMTIME_SSP_H + +#include +#include + +_Static_assert(_Alignof(int8_t) == 1, "non-wasi data layout"); +_Static_assert(_Alignof(uint8_t) == 1, "non-wasi data layout"); +_Static_assert(_Alignof(int16_t) == 2, "non-wasi data layout"); +_Static_assert(_Alignof(uint16_t) == 2, "non-wasi data layout"); +_Static_assert(_Alignof(int32_t) == 4, "non-wasi data layout"); +_Static_assert(_Alignof(uint32_t) == 4, "non-wasi data layout"); +_Static_assert(_Alignof(int64_t) == 8, "non-wasi data layout"); +_Static_assert(_Alignof(uint64_t) == 8, "non-wasi data layout"); + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint8_t __wasi_advice_t; +#define __WASI_ADVICE_NORMAL (0) +#define __WASI_ADVICE_SEQUENTIAL (1) +#define __WASI_ADVICE_RANDOM (2) +#define __WASI_ADVICE_WILLNEED (3) +#define __WASI_ADVICE_DONTNEED (4) +#define __WASI_ADVICE_NOREUSE (5) + +typedef uint32_t __wasi_clockid_t; +#define __WASI_CLOCK_REALTIME (0) +#define __WASI_CLOCK_MONOTONIC (1) +#define __WASI_CLOCK_PROCESS_CPUTIME_ID (2) +#define __WASI_CLOCK_THREAD_CPUTIME_ID (3) + +typedef uint64_t __wasi_device_t; + +typedef uint64_t __wasi_dircookie_t; +#define __WASI_DIRCOOKIE_START (0) + +typedef uint16_t __wasi_errno_t; +#define __WASI_ESUCCESS (0) +#define __WASI_E2BIG (1) +#define __WASI_EACCES (2) +#define __WASI_EADDRINUSE (3) +#define __WASI_EADDRNOTAVAIL (4) +#define __WASI_EAFNOSUPPORT (5) +#define __WASI_EAGAIN (6) +#define __WASI_EALREADY (7) +#define __WASI_EBADF (8) +#define __WASI_EBADMSG (9) +#define __WASI_EBUSY (10) +#define __WASI_ECANCELED (11) +#define __WASI_ECHILD (12) +#define __WASI_ECONNABORTED (13) +#define __WASI_ECONNREFUSED (14) +#define __WASI_ECONNRESET (15) +#define __WASI_EDEADLK (16) +#define __WASI_EDESTADDRREQ (17) +#define __WASI_EDOM (18) +#define __WASI_EDQUOT (19) +#define __WASI_EEXIST (20) +#define __WASI_EFAULT (21) +#define __WASI_EFBIG (22) +#define __WASI_EHOSTUNREACH (23) +#define __WASI_EIDRM (24) +#define __WASI_EILSEQ (25) +#define __WASI_EINPROGRESS (26) +#define __WASI_EINTR (27) +#define __WASI_EINVAL (28) +#define __WASI_EIO (29) +#define __WASI_EISCONN (30) +#define __WASI_EISDIR (31) +#define __WASI_ELOOP (32) +#define __WASI_EMFILE (33) +#define __WASI_EMLINK (34) +#define __WASI_EMSGSIZE (35) +#define __WASI_EMULTIHOP (36) +#define __WASI_ENAMETOOLONG (37) +#define __WASI_ENETDOWN (38) +#define __WASI_ENETRESET (39) +#define __WASI_ENETUNREACH (40) +#define __WASI_ENFILE (41) +#define __WASI_ENOBUFS (42) +#define __WASI_ENODEV (43) +#define __WASI_ENOENT (44) +#define __WASI_ENOEXEC (45) +#define __WASI_ENOLCK (46) +#define __WASI_ENOLINK (47) +#define __WASI_ENOMEM (48) +#define __WASI_ENOMSG (49) +#define __WASI_ENOPROTOOPT (50) +#define __WASI_ENOSPC (51) +#define __WASI_ENOSYS (52) +#define __WASI_ENOTCONN (53) +#define __WASI_ENOTDIR (54) +#define __WASI_ENOTEMPTY (55) +#define __WASI_ENOTRECOVERABLE (56) +#define __WASI_ENOTSOCK (57) +#define __WASI_ENOTSUP (58) +#define __WASI_ENOTTY (59) +#define __WASI_ENXIO (60) +#define __WASI_EOVERFLOW (61) +#define __WASI_EOWNERDEAD (62) +#define __WASI_EPERM (63) +#define __WASI_EPIPE (64) +#define __WASI_EPROTO (65) +#define __WASI_EPROTONOSUPPORT (66) +#define __WASI_EPROTOTYPE (67) +#define __WASI_ERANGE (68) +#define __WASI_EROFS (69) +#define __WASI_ESPIPE (70) +#define __WASI_ESRCH (71) +#define __WASI_ESTALE (72) +#define __WASI_ETIMEDOUT (73) +#define __WASI_ETXTBSY (74) +#define __WASI_EXDEV (75) +#define __WASI_ENOTCAPABLE (76) + +typedef uint16_t __wasi_eventrwflags_t; +#define __WASI_EVENT_FD_READWRITE_HANGUP (0x0001) + +typedef uint8_t __wasi_eventtype_t; +#define __WASI_EVENTTYPE_CLOCK (0) +#define __WASI_EVENTTYPE_FD_READ (1) +#define __WASI_EVENTTYPE_FD_WRITE (2) + +typedef uint32_t __wasi_exitcode_t; + +typedef uint32_t __wasi_fd_t; + +typedef uint16_t __wasi_fdflags_t; +#define __WASI_FDFLAG_APPEND (0x0001) +#define __WASI_FDFLAG_DSYNC (0x0002) +#define __WASI_FDFLAG_NONBLOCK (0x0004) +#define __WASI_FDFLAG_RSYNC (0x0008) +#define __WASI_FDFLAG_SYNC (0x0010) + +typedef int64_t __wasi_filedelta_t; + +typedef uint64_t __wasi_filesize_t; + +typedef uint8_t __wasi_filetype_t; +#define __WASI_FILETYPE_UNKNOWN (0) +#define __WASI_FILETYPE_BLOCK_DEVICE (1) +#define __WASI_FILETYPE_CHARACTER_DEVICE (2) +#define __WASI_FILETYPE_DIRECTORY (3) +#define __WASI_FILETYPE_REGULAR_FILE (4) +#define __WASI_FILETYPE_SOCKET_DGRAM (5) +#define __WASI_FILETYPE_SOCKET_STREAM (6) +#define __WASI_FILETYPE_SYMBOLIC_LINK (7) + +typedef uint16_t __wasi_fstflags_t; +#define __WASI_FILESTAT_SET_ATIM (0x0001) +#define __WASI_FILESTAT_SET_ATIM_NOW (0x0002) +#define __WASI_FILESTAT_SET_MTIM (0x0004) +#define __WASI_FILESTAT_SET_MTIM_NOW (0x0008) + +typedef uint64_t __wasi_inode_t; + +typedef uint32_t __wasi_linkcount_t; + +typedef uint32_t __wasi_lookupflags_t; +#define __WASI_LOOKUP_SYMLINK_FOLLOW (0x00000001) + +typedef uint16_t __wasi_oflags_t; +#define __WASI_O_CREAT (0x0001) +#define __WASI_O_DIRECTORY (0x0002) +#define __WASI_O_EXCL (0x0004) +#define __WASI_O_TRUNC (0x0008) + +typedef uint16_t __wasi_riflags_t; +#define __WASI_SOCK_RECV_PEEK (0x0001) +#define __WASI_SOCK_RECV_WAITALL (0x0002) + +typedef uint64_t __wasi_rights_t; +#define __WASI_RIGHT_FD_DATASYNC (0x0000000000000001) +#define __WASI_RIGHT_FD_READ (0x0000000000000002) +#define __WASI_RIGHT_FD_SEEK (0x0000000000000004) +#define __WASI_RIGHT_FD_FDSTAT_SET_FLAGS (0x0000000000000008) +#define __WASI_RIGHT_FD_SYNC (0x0000000000000010) +#define __WASI_RIGHT_FD_TELL (0x0000000000000020) +#define __WASI_RIGHT_FD_WRITE (0x0000000000000040) +#define __WASI_RIGHT_FD_ADVISE (0x0000000000000080) +#define __WASI_RIGHT_FD_ALLOCATE (0x0000000000000100) +#define __WASI_RIGHT_PATH_CREATE_DIRECTORY (0x0000000000000200) +#define __WASI_RIGHT_PATH_CREATE_FILE (0x0000000000000400) +#define __WASI_RIGHT_PATH_LINK_SOURCE (0x0000000000000800) +#define __WASI_RIGHT_PATH_LINK_TARGET (0x0000000000001000) +#define __WASI_RIGHT_PATH_OPEN (0x0000000000002000) +#define __WASI_RIGHT_FD_READDIR (0x0000000000004000) +#define __WASI_RIGHT_PATH_READLINK (0x0000000000008000) +#define __WASI_RIGHT_PATH_RENAME_SOURCE (0x0000000000010000) +#define __WASI_RIGHT_PATH_RENAME_TARGET (0x0000000000020000) +#define __WASI_RIGHT_PATH_FILESTAT_GET (0x0000000000040000) +#define __WASI_RIGHT_PATH_FILESTAT_SET_SIZE (0x0000000000080000) +#define __WASI_RIGHT_PATH_FILESTAT_SET_TIMES (0x0000000000100000) +#define __WASI_RIGHT_FD_FILESTAT_GET (0x0000000000200000) +#define __WASI_RIGHT_FD_FILESTAT_SET_SIZE (0x0000000000400000) +#define __WASI_RIGHT_FD_FILESTAT_SET_TIMES (0x0000000000800000) +#define __WASI_RIGHT_PATH_SYMLINK (0x0000000001000000) +#define __WASI_RIGHT_PATH_REMOVE_DIRECTORY (0x0000000002000000) +#define __WASI_RIGHT_PATH_UNLINK_FILE (0x0000000004000000) +#define __WASI_RIGHT_POLL_FD_READWRITE (0x0000000008000000) +#define __WASI_RIGHT_SOCK_SHUTDOWN (0x0000000010000000) + +typedef uint16_t __wasi_roflags_t; +#define __WASI_SOCK_RECV_DATA_TRUNCATED (0x0001) + +typedef uint8_t __wasi_sdflags_t; +#define __WASI_SHUT_RD (0x01) +#define __WASI_SHUT_WR (0x02) + +typedef uint16_t __wasi_siflags_t; + +typedef uint8_t __wasi_signal_t; +// 0 is reserved; POSIX has special semantics for kill(pid, 0). +#define __WASI_SIGHUP (1) +#define __WASI_SIGINT (2) +#define __WASI_SIGQUIT (3) +#define __WASI_SIGILL (4) +#define __WASI_SIGTRAP (5) +#define __WASI_SIGABRT (6) +#define __WASI_SIGBUS (7) +#define __WASI_SIGFPE (8) +#define __WASI_SIGKILL (9) +#define __WASI_SIGUSR1 (10) +#define __WASI_SIGSEGV (11) +#define __WASI_SIGUSR2 (12) +#define __WASI_SIGPIPE (13) +#define __WASI_SIGALRM (14) +#define __WASI_SIGTERM (15) +#define __WASI_SIGCHLD (16) +#define __WASI_SIGCONT (17) +#define __WASI_SIGSTOP (18) +#define __WASI_SIGTSTP (19) +#define __WASI_SIGTTIN (20) +#define __WASI_SIGTTOU (21) +#define __WASI_SIGURG (22) +#define __WASI_SIGXCPU (23) +#define __WASI_SIGXFSZ (24) +#define __WASI_SIGVTALRM (25) +#define __WASI_SIGPROF (26) +#define __WASI_SIGWINCH (27) +#define __WASI_SIGPOLL (28) +#define __WASI_SIGPWR (29) +#define __WASI_SIGSYS (30) + +typedef uint16_t __wasi_subclockflags_t; +#define __WASI_SUBSCRIPTION_CLOCK_ABSTIME (0x0001) + +typedef uint64_t __wasi_timestamp_t; + +typedef uint64_t __wasi_userdata_t; + +typedef uint8_t __wasi_whence_t; +#define __WASI_WHENCE_CUR (0) +#define __WASI_WHENCE_END (1) +#define __WASI_WHENCE_SET (2) + +typedef uint8_t __wasi_preopentype_t; +#define __WASI_PREOPENTYPE_DIR (0) + +struct fd_table; +struct fd_prestats; +struct argv_environ_values; + +typedef struct __wasi_dirent_t { + __wasi_dircookie_t d_next; + __wasi_inode_t d_ino; + uint32_t d_namlen; + __wasi_filetype_t d_type; +} __wasi_dirent_t; +_Static_assert(offsetof(__wasi_dirent_t, d_next) == 0, "non-wasi data layout"); +_Static_assert(offsetof(__wasi_dirent_t, d_ino) == 8, "non-wasi data layout"); +_Static_assert(offsetof(__wasi_dirent_t, d_namlen) == 16, "non-wasi data layout"); +_Static_assert(offsetof(__wasi_dirent_t, d_type) == 20, "non-wasi data layout"); +_Static_assert(sizeof(__wasi_dirent_t) == 24, "non-wasi data layout"); +_Static_assert(_Alignof(__wasi_dirent_t) == 8, "non-wasi data layout"); + +typedef struct __wasi_event_t { + __wasi_userdata_t userdata; + __wasi_errno_t error; + __wasi_eventtype_t type; + union __wasi_event_u { + struct __wasi_event_u_fd_readwrite_t { + __wasi_filesize_t nbytes; + __wasi_eventrwflags_t flags; + } fd_readwrite; + } u; +} __wasi_event_t; +_Static_assert(offsetof(__wasi_event_t, userdata) == 0, "non-wasi data layout"); +_Static_assert(offsetof(__wasi_event_t, error) == 8, "non-wasi data layout"); +_Static_assert(offsetof(__wasi_event_t, type) == 10, "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_event_t, u.fd_readwrite.nbytes) == 16, "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_event_t, u.fd_readwrite.flags) == 24, "non-wasi data layout"); +_Static_assert(sizeof(__wasi_event_t) == 32, "non-wasi data layout"); +_Static_assert(_Alignof(__wasi_event_t) == 8, "non-wasi data layout"); + +typedef struct __wasi_prestat_t { + __wasi_preopentype_t pr_type; + union __wasi_prestat_u { + struct __wasi_prestat_u_dir_t { + size_t pr_name_len; + } dir; + } u; +} __wasi_prestat_t; +_Static_assert(offsetof(__wasi_prestat_t, pr_type) == 0, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 4 || + offsetof(__wasi_prestat_t, u.dir.pr_name_len) == 4, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 8 || + offsetof(__wasi_prestat_t, u.dir.pr_name_len) == 8, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 4 || + sizeof(__wasi_prestat_t) == 8, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 8 || + sizeof(__wasi_prestat_t) == 16, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 4 || + _Alignof(__wasi_prestat_t) == 4, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 8 || + _Alignof(__wasi_prestat_t) == 8, "non-wasi data layout"); + +typedef struct __wasi_fdstat_t { + __wasi_filetype_t fs_filetype; + __wasi_fdflags_t fs_flags; + __wasi_rights_t fs_rights_base; + __wasi_rights_t fs_rights_inheriting; +} __wasi_fdstat_t; +_Static_assert( + offsetof(__wasi_fdstat_t, fs_filetype) == 0, "non-wasi data layout"); +_Static_assert(offsetof(__wasi_fdstat_t, fs_flags) == 2, "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_fdstat_t, fs_rights_base) == 8, "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_fdstat_t, fs_rights_inheriting) == 16, + "non-wasi data layout"); +_Static_assert(sizeof(__wasi_fdstat_t) == 24, "non-wasi data layout"); +_Static_assert(_Alignof(__wasi_fdstat_t) == 8, "non-wasi data layout"); + +typedef struct __wasi_filestat_t { + __wasi_device_t st_dev; + __wasi_inode_t st_ino; + __wasi_filetype_t st_filetype; + __wasi_linkcount_t st_nlink; + __wasi_filesize_t st_size; + __wasi_timestamp_t st_atim; + __wasi_timestamp_t st_mtim; + __wasi_timestamp_t st_ctim; +} __wasi_filestat_t; +_Static_assert(offsetof(__wasi_filestat_t, st_dev) == 0, "non-wasi data layout"); +_Static_assert(offsetof(__wasi_filestat_t, st_ino) == 8, "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_filestat_t, st_filetype) == 16, "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_filestat_t, st_nlink) == 20, "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_filestat_t, st_size) == 24, "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_filestat_t, st_atim) == 32, "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_filestat_t, st_mtim) == 40, "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_filestat_t, st_ctim) == 48, "non-wasi data layout"); +_Static_assert(sizeof(__wasi_filestat_t) == 56, "non-wasi data layout"); +_Static_assert(_Alignof(__wasi_filestat_t) == 8, "non-wasi data layout"); + +typedef struct __wasi_ciovec_t { + const void *buf; + size_t buf_len; +} __wasi_ciovec_t; +_Static_assert(offsetof(__wasi_ciovec_t, buf) == 0, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 4 || + offsetof(__wasi_ciovec_t, buf_len) == 4, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 8 || + offsetof(__wasi_ciovec_t, buf_len) == 8, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 4 || + sizeof(__wasi_ciovec_t) == 8, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 8 || + sizeof(__wasi_ciovec_t) == 16, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 4 || + _Alignof(__wasi_ciovec_t) == 4, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 8 || + _Alignof(__wasi_ciovec_t) == 8, "non-wasi data layout"); + +typedef struct __wasi_iovec_t { + void *buf; + size_t buf_len; +} __wasi_iovec_t; +_Static_assert(offsetof(__wasi_iovec_t, buf) == 0, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 4 || + offsetof(__wasi_iovec_t, buf_len) == 4, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 8 || + offsetof(__wasi_iovec_t, buf_len) == 8, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 4 || + sizeof(__wasi_iovec_t) == 8, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 8 || + sizeof(__wasi_iovec_t) == 16, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 4 || + _Alignof(__wasi_iovec_t) == 4, "non-wasi data layout"); +_Static_assert(sizeof(void *) != 8 || + _Alignof(__wasi_iovec_t) == 8, "non-wasi data layout"); + +typedef struct __wasi_subscription_t { + __wasi_userdata_t userdata; + __wasi_eventtype_t type; + union __wasi_subscription_u { + struct __wasi_subscription_u_clock_t { + __wasi_userdata_t identifier; + __wasi_clockid_t clock_id; + __wasi_timestamp_t timeout; + __wasi_timestamp_t precision; + __wasi_subclockflags_t flags; + } clock; + struct __wasi_subscription_u_fd_readwrite_t { + __wasi_fd_t fd; + } fd_readwrite; + } u; +} __wasi_subscription_t; +_Static_assert( + offsetof(__wasi_subscription_t, userdata) == 0, "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_subscription_t, type) == 8, "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_subscription_t, u.clock.identifier) == 16, + "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_subscription_t, u.clock.clock_id) == 24, + "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_subscription_t, u.clock.timeout) == 32, "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_subscription_t, u.clock.precision) == 40, + "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_subscription_t, u.clock.flags) == 48, "non-wasi data layout"); +_Static_assert( + offsetof(__wasi_subscription_t, u.fd_readwrite.fd) == 16, + "non-wasi data layout"); +_Static_assert(sizeof(__wasi_subscription_t) == 56, "non-wasi data layout"); +_Static_assert(_Alignof(__wasi_subscription_t) == 8, "non-wasi data layout"); + +#if defined(WASMTIME_SSP_WASI_API) +#define WASMTIME_SSP_SYSCALL_NAME(name) \ + asm("__wasi_" #name) +#else +#define WASMTIME_SSP_SYSCALL_NAME(name) +#endif + +__wasi_errno_t wasmtime_ssp_args_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *arg_environ, +#endif + char **argv, + char *argv_buf +) WASMTIME_SSP_SYSCALL_NAME(args_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_args_sizes_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *arg_environ, +#endif + size_t *argc, + size_t *argv_buf_size +) WASMTIME_SSP_SYSCALL_NAME(args_sizes_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_clock_res_get( + __wasi_clockid_t clock_id, + __wasi_timestamp_t *resolution +) WASMTIME_SSP_SYSCALL_NAME(clock_res_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_clock_time_get( + __wasi_clockid_t clock_id, + __wasi_timestamp_t precision, + __wasi_timestamp_t *time +) WASMTIME_SSP_SYSCALL_NAME(clock_time_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_environ_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *arg_environ, +#endif + char **environ, + char *environ_buf +) WASMTIME_SSP_SYSCALL_NAME(environ_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_environ_sizes_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *arg_environ, +#endif + size_t *environ_count, + size_t *environ_buf_size +) WASMTIME_SSP_SYSCALL_NAME(environ_sizes_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_prestat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_prestats *prestats, +#endif + __wasi_fd_t fd, + __wasi_prestat_t *buf +) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_prestat_dir_name( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_prestats *prestats, +#endif + __wasi_fd_t fd, + char *path, + size_t path_len +) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_dir_name) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_close( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, + struct fd_prestats *prestats, +#endif + __wasi_fd_t fd +) WASMTIME_SSP_SYSCALL_NAME(fd_close) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_datasync( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd +) WASMTIME_SSP_SYSCALL_NAME(fd_datasync) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_pread( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const __wasi_iovec_t *iovs, + size_t iovs_len, + __wasi_filesize_t offset, + size_t *nread +) WASMTIME_SSP_SYSCALL_NAME(fd_pread) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_pwrite( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const __wasi_ciovec_t *iovs, + size_t iovs_len, + __wasi_filesize_t offset, + size_t *nwritten +) WASMTIME_SSP_SYSCALL_NAME(fd_pwrite) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_read( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const __wasi_iovec_t *iovs, + size_t iovs_len, + size_t *nread +) WASMTIME_SSP_SYSCALL_NAME(fd_read) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_renumber( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, + struct fd_prestats *prestats, +#endif + __wasi_fd_t from, + __wasi_fd_t to +) WASMTIME_SSP_SYSCALL_NAME(fd_renumber) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_seek( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filedelta_t offset, + __wasi_whence_t whence, + __wasi_filesize_t *newoffset +) WASMTIME_SSP_SYSCALL_NAME(fd_seek) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_tell( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filesize_t *newoffset +) WASMTIME_SSP_SYSCALL_NAME(fd_tell) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_fdstat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_fdstat_t *buf +) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_fdstat_set_flags( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_fdflags_t flags +) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_flags) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_fdstat_set_rights( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_rights_t fs_rights_base, + __wasi_rights_t fs_rights_inheriting +) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_rights) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_sync( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd +) WASMTIME_SSP_SYSCALL_NAME(fd_sync) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_write( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const __wasi_ciovec_t *iovs, + size_t iovs_len, + size_t *nwritten +) WASMTIME_SSP_SYSCALL_NAME(fd_write) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_advise( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filesize_t offset, + __wasi_filesize_t len, + __wasi_advice_t advice +) WASMTIME_SSP_SYSCALL_NAME(fd_advise) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_allocate( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filesize_t offset, + __wasi_filesize_t len +) WASMTIME_SSP_SYSCALL_NAME(fd_allocate) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_create_directory( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const char *path, + size_t path_len +) WASMTIME_SSP_SYSCALL_NAME(path_create_directory) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_link( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t old_fd, + __wasi_lookupflags_t old_flags, + const char *old_path, + size_t old_path_len, + __wasi_fd_t new_fd, + const char *new_path, + size_t new_path_len +) WASMTIME_SSP_SYSCALL_NAME(path_link) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_open( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t dirfd, + __wasi_lookupflags_t dirflags, + const char *path, + size_t path_len, + __wasi_oflags_t oflags, + __wasi_rights_t fs_rights_base, + __wasi_rights_t fs_rights_inheriting, + __wasi_fdflags_t fs_flags, + __wasi_fd_t *fd +) WASMTIME_SSP_SYSCALL_NAME(path_open) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_readdir( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + void *buf, + size_t buf_len, + __wasi_dircookie_t cookie, + size_t *bufused +) WASMTIME_SSP_SYSCALL_NAME(fd_readdir) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_readlink( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const char *path, + size_t path_len, + char *buf, + size_t buf_len, + size_t *bufused +) WASMTIME_SSP_SYSCALL_NAME(path_readlink) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_rename( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t old_fd, + const char *old_path, + size_t old_path_len, + __wasi_fd_t new_fd, + const char *new_path, + size_t new_path_len +) WASMTIME_SSP_SYSCALL_NAME(path_rename) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_filestat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filestat_t *buf +) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_filestat_set_times( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_timestamp_t st_atim, + __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags +) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_times) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_fd_filestat_set_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filesize_t st_size +) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_size) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_filestat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_lookupflags_t flags, + const char *path, + size_t path_len, + __wasi_filestat_t *buf +) WASMTIME_SSP_SYSCALL_NAME(path_filestat_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_filestat_set_times( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_lookupflags_t flags, + const char *path, + size_t path_len, + __wasi_timestamp_t st_atim, + __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags +) WASMTIME_SSP_SYSCALL_NAME(path_filestat_set_times) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_symlink( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + const char *old_path, + size_t old_path_len, + __wasi_fd_t fd, + const char *new_path, + size_t new_path_len +) WASMTIME_SSP_SYSCALL_NAME(path_symlink) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_unlink_file( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const char *path, + size_t path_len +) WASMTIME_SSP_SYSCALL_NAME(path_unlink_file) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_path_remove_directory( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const char *path, + size_t path_len +) WASMTIME_SSP_SYSCALL_NAME(path_remove_directory) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_poll_oneoff( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + const __wasi_subscription_t *in, + __wasi_event_t *out, + size_t nsubscriptions, + size_t *nevents +) WASMTIME_SSP_SYSCALL_NAME(poll_oneoff) __attribute__((__warn_unused_result__)); + +_Noreturn void wasmtime_ssp_proc_exit( + __wasi_exitcode_t rval +) WASMTIME_SSP_SYSCALL_NAME(proc_exit); + +__wasi_errno_t wasmtime_ssp_proc_raise( + __wasi_signal_t sig +) WASMTIME_SSP_SYSCALL_NAME(proc_raise) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_random_get( + void *buf, + size_t buf_len +) WASMTIME_SSP_SYSCALL_NAME(random_get) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_recv( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + const __wasi_iovec_t *ri_data, + size_t ri_data_len, + __wasi_riflags_t ri_flags, + size_t *ro_datalen, + __wasi_roflags_t *ro_flags +) WASMTIME_SSP_SYSCALL_NAME(sock_recv) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_send( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + const __wasi_ciovec_t *si_data, + size_t si_data_len, + __wasi_siflags_t si_flags, + size_t *so_datalen +) WASMTIME_SSP_SYSCALL_NAME(sock_send) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sock_shutdown( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + __wasi_sdflags_t how +) WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) __attribute__((__warn_unused_result__)); + +__wasi_errno_t wasmtime_ssp_sched_yield(void) + WASMTIME_SSP_SYSCALL_NAME(sched_yield) __attribute__((__warn_unused_result__)); + +#ifdef __cplusplus +} +#endif + +#undef WASMTIME_SSP_SYSCALL_NAME + +#endif diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/LICENSE b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/LICENSE new file mode 100644 index 000000000..04c6f48a2 --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/LICENSE @@ -0,0 +1,24 @@ +All code is distributed under the following license: + + Copyright (c) 2015 Nuxi, https://nuxi.nl/ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/README.md b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/README.md new file mode 100644 index 000000000..fe73057f5 --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/README.md @@ -0,0 +1,14 @@ +This directory consists of selected files copied from the [libemulator] +directory in the [cloudabi-utils] repository, with minor modifications, +along with the accompanying LICENSE file from that repository. + +The modifications are marked with `WASMTIME_*` preprocessor macros. + +The files were copied at git revision +223dadc53248552db43e012c67ed08cf416a2b12 +which is dated +Tue Jun 25 17:22:07 2019 -0700 +. + +[libemulator]: https://github.com/NuxiNL/cloudabi-utils/tree/master/src/libemulator +[cloudabi-utils]: https://github.com/NuxiNL/cloudabi-utils diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/config.h b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/config.h new file mode 100644 index 000000000..714e29d24 --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/config.h @@ -0,0 +1,100 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://github.com/CraneStation/wasmtime/blob/master/LICENSE for license information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/CraneStation/wasmtime/blob/master/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#ifndef CONFIG_H +#define CONFIG_H + +#include + +#if defined(__FreeBSD__) || defined(__APPLE__) +#define CONFIG_HAS_ARC4RANDOM_BUF 1 +#else +#define CONFIG_HAS_ARC4RANDOM_BUF 0 +#endif + +// On Linux, prefer to use getrandom, though it isn't available in +// GLIBC before 2.25. +#if defined(__linux__) && \ + (!defined(__GLIBC__) || \ + __GLIBC__ > 2 || \ + (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)) +#define CONFIG_HAS_GETRANDOM 1 +#else +#define CONFIG_HAS_GETRANDOM 0 +#endif + +#if defined(__CloudABI__) +#define CONFIG_HAS_CAP_ENTER 1 +#else +#define CONFIG_HAS_CAP_ENTER 0 +#endif + +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__EMSCRIPTEN__) +#define CONFIG_HAS_CLOCK_NANOSLEEP 1 +#else +#define CONFIG_HAS_CLOCK_NANOSLEEP 0 +#endif + +#if !defined(__APPLE__) && !defined(__FreeBSD__) +#define CONFIG_HAS_FDATASYNC 1 +#else +#define CONFIG_HAS_FDATASYNC 0 +#endif + +#ifndef __CloudABI__ +#define CONFIG_HAS_ISATTY 1 +#else +#define CONFIG_HAS_ISATTY 0 +#endif + +#ifndef __APPLE__ +#define CONFIG_HAS_POSIX_FALLOCATE 1 +#else +#define CONFIG_HAS_POSIX_FALLOCATE 0 +#endif + +#ifndef __APPLE__ +#define CONFIG_HAS_PREADV 1 +#else +#define CONFIG_HAS_PREADV 0 +#endif + +#if defined(__APPLE__) || defined(__CloudABI__) +#define CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP 1 +#else +#define CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP 0 +#endif + +#ifndef __APPLE__ +#define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 1 +#else +#define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 0 +#endif + +#ifndef __APPLE__ +#define CONFIG_HAS_PWRITEV 1 +#else +#define CONFIG_HAS_PWRITEV 0 +#endif + +#ifdef __APPLE__ +#define st_atimespec st_atim +#define st_mtimespec st_mtim +#define st_ctimespec st_ctim +#endif + +#ifdef __APPLE__ +#define CONFIG_TLS_USE_GSBASE 1 +#else +#define CONFIG_TLS_USE_GSBASE 0 +#endif + +#endif diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/locking.h b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/locking.h new file mode 100644 index 000000000..0efb788ed --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/locking.h @@ -0,0 +1,215 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://github.com/CraneStation/wasmtime/blob/master/LICENSE for license information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/CraneStation/wasmtime/blob/master/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#ifndef LOCKING_H +#define LOCKING_H + +#include "config.h" + +#include +#include +#include +#include +#include + +#ifndef __has_extension +#define __has_extension(x) 0 +#endif + +#if __has_extension(c_thread_safety_attributes) +#define LOCK_ANNOTATE(x) __attribute__((x)) +#else +#define LOCK_ANNOTATE(x) +#endif + +// Lock annotation macros. + +#define LOCKABLE LOCK_ANNOTATE(lockable) + +#define LOCKS_EXCLUSIVE(...) LOCK_ANNOTATE(exclusive_lock_function(__VA_ARGS__)) +#define LOCKS_SHARED(...) LOCK_ANNOTATE(shared_lock_function(__VA_ARGS__)) + +#define TRYLOCKS_EXCLUSIVE(...) \ + LOCK_ANNOTATE(exclusive_trylock_function(__VA_ARGS__)) +#define TRYLOCKS_SHARED(...) LOCK_ANNOTATE(shared_trylock_function(__VA_ARGS__)) + +#define UNLOCKS(...) LOCK_ANNOTATE(unlock_function(__VA_ARGS__)) + +#define REQUIRES_EXCLUSIVE(...) \ + LOCK_ANNOTATE(exclusive_locks_required(__VA_ARGS__)) +#define REQUIRES_SHARED(...) LOCK_ANNOTATE(shared_locks_required(__VA_ARGS__)) +#define REQUIRES_UNLOCKED(...) LOCK_ANNOTATE(locks_excluded(__VA_ARGS__)) + +#define NO_LOCK_ANALYSIS LOCK_ANNOTATE(no_thread_safety_analysis) + +// Mutex that uses the lock annotations. + +struct LOCKABLE mutex { + pthread_mutex_t object; +}; + +#define MUTEX_INITIALIZER \ + { PTHREAD_MUTEX_INITIALIZER } + +static inline void mutex_init(struct mutex *lock) REQUIRES_UNLOCKED(*lock) { + pthread_mutex_init(&lock->object, NULL); +} + +static inline void mutex_destroy(struct mutex *lock) REQUIRES_UNLOCKED(*lock) { + pthread_mutex_destroy(&lock->object); +} + +static inline void mutex_lock(struct mutex *lock) + LOCKS_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS { + pthread_mutex_lock(&lock->object); +} + +static inline void mutex_unlock(struct mutex *lock) + UNLOCKS(*lock) NO_LOCK_ANALYSIS { + pthread_mutex_unlock(&lock->object); +} + +// Read-write lock that uses the lock annotations. + +struct LOCKABLE rwlock { + pthread_rwlock_t object; +}; + +static inline void rwlock_init(struct rwlock *lock) REQUIRES_UNLOCKED(*lock) { + pthread_rwlock_init(&lock->object, NULL); +} + +static inline void rwlock_rdlock(struct rwlock *lock) + LOCKS_SHARED(*lock) NO_LOCK_ANALYSIS { + pthread_rwlock_rdlock(&lock->object); +} + +static inline void rwlock_wrlock(struct rwlock *lock) + LOCKS_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS { + pthread_rwlock_wrlock(&lock->object); +} + +static inline void rwlock_unlock(struct rwlock *lock) + UNLOCKS(*lock) NO_LOCK_ANALYSIS { + pthread_rwlock_unlock(&lock->object); +} + +// Condition variable that uses the lock annotations. + +struct LOCKABLE cond { + pthread_cond_t object; +#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK || \ + !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP + clockid_t clock; +#endif +}; + +static inline void cond_init_monotonic(struct cond *cond) { +#if CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK + pthread_condattr_t attr; + pthread_condattr_init(&attr); + pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + pthread_cond_init(&cond->object, &attr); + pthread_condattr_destroy(&attr); +#else + pthread_cond_init(&cond->object, NULL); +#endif +#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK || \ + !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP + cond->clock = CLOCK_MONOTONIC; +#endif +} + +static inline void cond_init_realtime(struct cond *cond) { + pthread_cond_init(&cond->object, NULL); +#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK || \ + !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP + cond->clock = CLOCK_REALTIME; +#endif +} + +static inline void cond_destroy(struct cond *cond) { + pthread_cond_destroy(&cond->object); +} + +static inline void cond_signal(struct cond *cond) { + pthread_cond_signal(&cond->object); +} + +static inline bool cond_timedwait(struct cond *cond, struct mutex *lock, + uint64_t timeout, bool abstime) + REQUIRES_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS { + struct timespec ts = { + .tv_sec = (time_t)(timeout / 1000000000), + .tv_nsec = (long)(timeout % 1000000000), + }; + + if (abstime) { +#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK + // No native support for sleeping on monotonic clocks. Convert the + // timeout to a relative value and then to an absolute value for the + // realtime clock. + if (cond->clock != CLOCK_REALTIME) { + struct timespec ts_monotonic; + clock_gettime(cond->clock, &ts_monotonic); + ts.tv_sec -= ts_monotonic.tv_sec; + ts.tv_nsec -= ts_monotonic.tv_nsec; + if (ts.tv_nsec < 0) { + ts.tv_nsec += 1000000000; + --ts.tv_sec; + } + + struct timespec ts_realtime; + clock_gettime(CLOCK_REALTIME, &ts_realtime); + ts.tv_sec += ts_realtime.tv_sec; + ts.tv_nsec += ts_realtime.tv_nsec; + if (ts.tv_nsec >= 1000000000) { + ts.tv_nsec -= 1000000000; + ++ts.tv_sec; + } + } +#endif + } else { +#if CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP + // Implementation supports relative timeouts. + int ret = + pthread_cond_timedwait_relative_np(&cond->object, &lock->object, &ts); + assert((ret == 0 || ret == ETIMEDOUT) && + "pthread_cond_timedwait_relative_np() failed"); + return ret == ETIMEDOUT; +#else + // Convert to absolute timeout. + struct timespec ts_now; +#if CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK + clock_gettime(cond->clock, &ts_now); +#else + clock_gettime(CLOCK_REALTIME, &ts_now); +#endif + ts.tv_sec += ts_now.tv_sec; + ts.tv_nsec += ts_now.tv_nsec; + if (ts.tv_nsec >= 1000000000) { + ts.tv_nsec -= 1000000000; + ++ts.tv_sec; + } +#endif + } + + int ret = pthread_cond_timedwait(&cond->object, &lock->object, &ts); + assert((ret == 0 || ret == ETIMEDOUT) && "pthread_cond_timedwait() failed"); + return ret == ETIMEDOUT; +} + +static inline void cond_wait(struct cond *cond, struct mutex *lock) + REQUIRES_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS { + pthread_cond_wait(&cond->object, &lock->object); +} + +#endif diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/numeric_limits.h b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/numeric_limits.h new file mode 100644 index 000000000..30dddd19a --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/numeric_limits.h @@ -0,0 +1,42 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://github.com/CraneStation/wasmtime/blob/master/LICENSE for license information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/CraneStation/wasmtime/blob/master/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2015 Nuxi, https://nuxi.nl/ + +#ifndef COMMON_LIMITS_H +#define COMMON_LIMITS_H + +#include + +#define NUMERIC_MIN(t) \ + _Generic((t)0, char \ + : CHAR_MIN, signed char \ + : SCHAR_MIN, unsigned char : 0, short \ + : SHRT_MIN, unsigned short : 0, int \ + : INT_MIN, unsigned int : 0, long \ + : LONG_MIN, unsigned long : 0, long long \ + : LLONG_MIN, unsigned long long : 0, default \ + : (void)0) + +#define NUMERIC_MAX(t) \ + _Generic((t)0, char \ + : CHAR_MAX, signed char \ + : SCHAR_MAX, unsigned char \ + : UCHAR_MAX, short \ + : SHRT_MAX, unsigned short \ + : USHRT_MAX, int \ + : INT_MAX, unsigned int \ + : UINT_MAX, long \ + : LONG_MAX, unsigned long \ + : ULONG_MAX, long long \ + : LLONG_MAX, unsigned long long \ + : ULLONG_MAX, default \ + : (void)0) + +#endif diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.c b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.c new file mode 100644 index 000000000..45c138c92 --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.c @@ -0,0 +1,2888 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://github.com/CraneStation/wasmtime/blob/master/LICENSE for license information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/CraneStation/wasmtime/blob/master/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016-2018 Nuxi, https://nuxi.nl/ + +#include "config.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "locking.h" +#include "numeric_limits.h" +#include "posix.h" +#include "random.h" +#include "refcount.h" +#include "rights.h" +#include "str.h" + +#include "bh_common.h" +#include "bh_memory.h" + +// struct iovec must have the same layout as __wasi_iovec_t. +static_assert(offsetof(struct iovec, iov_base) == + offsetof(__wasi_iovec_t, buf), + "Offset mismatch"); +static_assert(sizeof(((struct iovec *)0)->iov_base) == + sizeof(((__wasi_iovec_t *)0)->buf), + "Size mismatch"); +static_assert(offsetof(struct iovec, iov_len) == + offsetof(__wasi_iovec_t, buf_len), + "Offset mismatch"); +static_assert(sizeof(((struct iovec *)0)->iov_len) == + sizeof(((__wasi_iovec_t *)0)->buf_len), + "Size mismatch"); +static_assert(sizeof(struct iovec) == sizeof(__wasi_iovec_t), + "Size mismatch"); + +// struct iovec must have the same layout as __wasi_ciovec_t. +static_assert(offsetof(struct iovec, iov_base) == + offsetof(__wasi_ciovec_t, buf), + "Offset mismatch"); +static_assert(sizeof(((struct iovec *)0)->iov_base) == + sizeof(((__wasi_ciovec_t *)0)->buf), + "Size mismatch"); +static_assert(offsetof(struct iovec, iov_len) == + offsetof(__wasi_ciovec_t, buf_len), + "Offset mismatch"); +static_assert(sizeof(((struct iovec *)0)->iov_len) == + sizeof(((__wasi_ciovec_t *)0)->buf_len), + "Size mismatch"); +static_assert(sizeof(struct iovec) == sizeof(__wasi_ciovec_t), + "Size mismatch"); + +#if defined(WASMTIME_SSP_STATIC_CURFDS) +static __thread struct fd_table *curfds; +static __thread struct fd_prestats *prestats; +static __thread struct argv_environ_values *argv_environ; +#endif + +// Converts a POSIX error code to a CloudABI error code. +static __wasi_errno_t convert_errno(int error) { + static const __wasi_errno_t errors[] = { +#define X(v) [v] = __WASI_##v + X(E2BIG), + X(EACCES), + X(EADDRINUSE), + X(EADDRNOTAVAIL), + X(EAFNOSUPPORT), + X(EAGAIN), + X(EALREADY), + X(EBADF), + X(EBADMSG), + X(EBUSY), + X(ECANCELED), + X(ECHILD), + X(ECONNABORTED), + X(ECONNREFUSED), + X(ECONNRESET), + X(EDEADLK), + X(EDESTADDRREQ), + X(EDOM), + X(EDQUOT), + X(EEXIST), + X(EFAULT), + X(EFBIG), + X(EHOSTUNREACH), + X(EIDRM), + X(EILSEQ), + X(EINPROGRESS), + X(EINTR), + X(EINVAL), + X(EIO), + X(EISCONN), + X(EISDIR), + X(ELOOP), + X(EMFILE), + X(EMLINK), + X(EMSGSIZE), + X(EMULTIHOP), + X(ENAMETOOLONG), + X(ENETDOWN), + X(ENETRESET), + X(ENETUNREACH), + X(ENFILE), + X(ENOBUFS), + X(ENODEV), + X(ENOENT), + X(ENOEXEC), + X(ENOLCK), + X(ENOLINK), + X(ENOMEM), + X(ENOMSG), + X(ENOPROTOOPT), + X(ENOSPC), + X(ENOSYS), +#ifdef ENOTCAPABLE + X(ENOTCAPABLE), +#endif + X(ENOTCONN), + X(ENOTDIR), + X(ENOTEMPTY), + X(ENOTRECOVERABLE), + X(ENOTSOCK), + X(ENOTSUP), + X(ENOTTY), + X(ENXIO), + X(EOVERFLOW), + X(EOWNERDEAD), + X(EPERM), + X(EPIPE), + X(EPROTO), + X(EPROTONOSUPPORT), + X(EPROTOTYPE), + X(ERANGE), + X(EROFS), + X(ESPIPE), + X(ESRCH), + X(ESTALE), + X(ETIMEDOUT), + X(ETXTBSY), + X(EXDEV), +#undef X +#if EOPNOTSUPP != ENOTSUP + [EOPNOTSUPP] = __WASI_ENOTSUP, +#endif +#if EWOULDBLOCK != EAGAIN + [EWOULDBLOCK] = __WASI_EAGAIN, +#endif + }; + if (error < 0 || (size_t)error >= sizeof(errors) / sizeof(errors[0]) || + errors[error] == 0) + return __WASI_ENOSYS; + return errors[error]; +} + +// Converts a POSIX timespec to a CloudABI timestamp. +static __wasi_timestamp_t convert_timespec( + const struct timespec *ts +) { + if (ts->tv_sec < 0) + return 0; + if ((__wasi_timestamp_t)ts->tv_sec >= UINT64_MAX / 1000000000) + return UINT64_MAX; + return (__wasi_timestamp_t)ts->tv_sec * 1000000000 + (__wasi_timestamp_t)ts->tv_nsec; +} + +// Converts a CloudABI clock identifier to a POSIX clock identifier. +static bool convert_clockid( + __wasi_clockid_t in, + clockid_t *out +) { + switch (in) { + case __WASI_CLOCK_MONOTONIC: + *out = CLOCK_MONOTONIC; + return true; + case __WASI_CLOCK_PROCESS_CPUTIME_ID: + *out = CLOCK_PROCESS_CPUTIME_ID; + return true; + case __WASI_CLOCK_REALTIME: + *out = CLOCK_REALTIME; + return true; + case __WASI_CLOCK_THREAD_CPUTIME_ID: + *out = CLOCK_THREAD_CPUTIME_ID; + return true; + default: + return false; + } +} + +__wasi_errno_t wasmtime_ssp_clock_res_get( + __wasi_clockid_t clock_id, + __wasi_timestamp_t *resolution +) { + clockid_t nclock_id; + if (!convert_clockid(clock_id, &nclock_id)) + return __WASI_EINVAL; + struct timespec ts; + if (clock_getres(nclock_id, &ts) < 0) + return convert_errno(errno); + *resolution = convert_timespec(&ts); + return 0; +} + +__wasi_errno_t wasmtime_ssp_clock_time_get( + __wasi_clockid_t clock_id, + __wasi_timestamp_t precision, + __wasi_timestamp_t *time +) { + clockid_t nclock_id; + if (!convert_clockid(clock_id, &nclock_id)) + return __WASI_EINVAL; + struct timespec ts; + if (clock_gettime(nclock_id, &ts) < 0) + return convert_errno(errno); + *time = convert_timespec(&ts); + return 0; +} + +struct fd_prestat { + const char *dir; +}; + +void fd_prestats_init( + struct fd_prestats *pt +) { + rwlock_init(&pt->lock); + pt->prestats = NULL; + pt->size = 0; + pt->used = 0; +#if defined(WASMTIME_SSP_STATIC_CURFDS) + prestats = pt; +#endif +} + +// Grows the preopened resource table to a required lower bound and a +// minimum number of free preopened resource table entries. +static bool fd_prestats_grow( + struct fd_prestats *pt, + size_t min, + size_t incr +) REQUIRES_EXCLUSIVE(pt->lock) { + if (pt->size <= min || pt->size < (pt->used + incr) * 2) { + // Keep on doubling the table size until we've met our constraints. + size_t size = pt->size == 0 ? 1 : pt->size; + while (size <= min || size < (pt->used + incr) * 2) + size *= 2; + + // Grow the file descriptor table's allocation. + struct fd_prestat *prestats = bh_malloc((uint32)(sizeof(*prestats) * size)); + if (prestats == NULL) + return false; + + if (pt->prestats && pt->size > 0) { + bh_memcpy_s(prestats, (uint32)(sizeof(*prestats) * size), + pt->prestats, (uint32)(sizeof(*prestats) * pt->size)); + } + + if (pt->prestats) + bh_free(pt->prestats); + + // Mark all new file descriptors as unused. + for (size_t i = pt->size; i < size; ++i) + prestats[i].dir = NULL; + pt->prestats = prestats; + pt->size = size; + } + return true; +} + +// Inserts a preopened resource record into the preopened resource table. +bool fd_prestats_insert( + struct fd_prestats *pt, + const char *dir, + __wasi_fd_t fd +) { + // Grow the preopened resource table if needed. + rwlock_wrlock(&pt->lock); + if (!fd_prestats_grow(pt, fd, 1)) { + rwlock_unlock(&pt->lock); + return false; + } + + pt->prestats[fd].dir = bh_strdup(dir); + rwlock_unlock(&pt->lock); + + if (pt->prestats[fd].dir == NULL) + return false; + + return true; +} + +// Looks up a preopened resource table entry by number. +static __wasi_errno_t fd_prestats_get_entry( + struct fd_prestats *pt, + __wasi_fd_t fd, + struct fd_prestat **ret +) REQUIRES_SHARED(pt->lock) { + // Test for file descriptor existence. + if (fd >= pt->size) + return __WASI_EBADF; + struct fd_prestat *prestat = &pt->prestats[fd]; + if (prestat->dir == NULL) + return __WASI_EBADF; + + *ret = prestat; + return 0; +} + +struct fd_object { + struct refcount refcount; + __wasi_filetype_t type; + int number; + + union { + // Data associated with directory file descriptors. + struct { + struct mutex lock; // Lock to protect members below. + DIR *handle; // Directory handle. + __wasi_dircookie_t offset; // Offset of the directory. + } directory; + }; +}; + +struct fd_entry { + struct fd_object *object; + __wasi_rights_t rights_base; + __wasi_rights_t rights_inheriting; +}; + +void fd_table_init( + struct fd_table *ft +) { + rwlock_init(&ft->lock); + ft->entries = NULL; + ft->size = 0; + ft->used = 0; +#if defined(WASMTIME_SSP_STATIC_CURFDS) + curfds = ft; +#endif +} + +// Looks up a file descriptor table entry by number and required rights. +static __wasi_errno_t fd_table_get_entry( + struct fd_table *ft, + __wasi_fd_t fd, + __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting, + struct fd_entry **ret +) REQUIRES_SHARED(ft->lock) { + // Test for file descriptor existence. + if (fd >= ft->size) + return __WASI_EBADF; + struct fd_entry *fe = &ft->entries[fd]; + if (fe->object == NULL) + return __WASI_EBADF; + + // Validate rights. + if ((~fe->rights_base & rights_base) != 0 || + (~fe->rights_inheriting & rights_inheriting) != 0) + return __WASI_ENOTCAPABLE; + *ret = fe; + return 0; +} + +// Grows the file descriptor table to a required lower bound and a +// minimum number of free file descriptor table entries. +static bool fd_table_grow( + struct fd_table *ft, + size_t min, + size_t incr +) REQUIRES_EXCLUSIVE(ft->lock) { + if (ft->size <= min || ft->size < (ft->used + incr) * 2) { + // Keep on doubling the table size until we've met our constraints. + size_t size = ft->size == 0 ? 1 : ft->size; + while (size <= min || size < (ft->used + incr) * 2) + size *= 2; + + // Grow the file descriptor table's allocation. + struct fd_entry *entries = bh_malloc((uint32)(sizeof(*entries) * size)); + if (entries == NULL) + return false; + + if (ft->entries && ft->size > 0) { + bh_memcpy_s(entries, (uint32)(sizeof(*entries) * size), + ft->entries, (uint32)(sizeof(*entries) * ft->size)); + } + + if (ft->entries) + bh_free(ft->entries); + + // Mark all new file descriptors as unused. + for (size_t i = ft->size; i < size; ++i) + entries[i].object = NULL; + ft->entries = entries; + ft->size = size; + } + return true; +} + +// Allocates a new file descriptor object. +static __wasi_errno_t fd_object_new( + __wasi_filetype_t type, + struct fd_object **fo +) TRYLOCKS_SHARED(0, (*fo)->refcount) { + *fo = bh_malloc(sizeof(**fo)); + if (*fo == NULL) + return __WASI_ENOMEM; + refcount_init(&(*fo)->refcount, 1); + (*fo)->type = type; + (*fo)->number = -1; + return 0; +} + +// Attaches a file descriptor to the file descriptor table. +static void fd_table_attach( + struct fd_table *ft, + __wasi_fd_t fd, + struct fd_object *fo, + __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting +) REQUIRES_EXCLUSIVE(ft->lock) CONSUMES(fo->refcount) { + assert(ft->size > fd && "File descriptor table too small"); + struct fd_entry *fe = &ft->entries[fd]; + assert(fe->object == NULL && "Attempted to overwrite an existing descriptor"); + fe->object = fo; + fe->rights_base = rights_base; + fe->rights_inheriting = rights_inheriting; + ++ft->used; + assert(ft->size >= ft->used * 2 && "File descriptor too full"); +} + +// Detaches a file descriptor from the file descriptor table. +static void fd_table_detach( + struct fd_table *ft, + __wasi_fd_t fd, + struct fd_object **fo +) REQUIRES_EXCLUSIVE(ft->lock) PRODUCES((*fo)->refcount) { + assert(ft->size > fd && "File descriptor table too small"); + struct fd_entry *fe = &ft->entries[fd]; + *fo = fe->object; + assert(*fo != NULL && "Attempted to detach nonexistent descriptor"); + fe->object = NULL; + assert(ft->used > 0 && "Reference count mismatch"); + --ft->used; +} + +// Determines the type of a file descriptor and its maximum set of +// rights that should be attached to it. +static __wasi_errno_t fd_determine_type_rights( + int fd, + __wasi_filetype_t *type, + __wasi_rights_t *rights_base, + __wasi_rights_t *rights_inheriting +) { + struct stat sb; + if (fstat(fd, &sb) < 0) + return convert_errno(errno); + if (S_ISBLK(sb.st_mode)) { + *type = __WASI_FILETYPE_BLOCK_DEVICE; + *rights_base = RIGHTS_BLOCK_DEVICE_BASE; + *rights_inheriting = RIGHTS_BLOCK_DEVICE_INHERITING; + } else if (S_ISCHR(sb.st_mode)) { + *type = __WASI_FILETYPE_CHARACTER_DEVICE; +#if CONFIG_HAS_ISATTY + if (isatty(fd)) { + *rights_base = RIGHTS_TTY_BASE; + *rights_inheriting = RIGHTS_TTY_INHERITING; + } else +#endif + { + *rights_base = RIGHTS_CHARACTER_DEVICE_BASE; + *rights_inheriting = RIGHTS_CHARACTER_DEVICE_INHERITING; + } + } else if (S_ISDIR(sb.st_mode)) { + *type = __WASI_FILETYPE_DIRECTORY; + *rights_base = RIGHTS_DIRECTORY_BASE; + *rights_inheriting = RIGHTS_DIRECTORY_INHERITING; + } else if (S_ISREG(sb.st_mode)) { + *type = __WASI_FILETYPE_REGULAR_FILE; + *rights_base = RIGHTS_REGULAR_FILE_BASE; + *rights_inheriting = RIGHTS_REGULAR_FILE_INHERITING; + } else if (S_ISSOCK(sb.st_mode)) { + int socktype; + socklen_t socktypelen = sizeof(socktype); + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &socktype, &socktypelen) < 0) + return convert_errno(errno); + switch (socktype) { + case SOCK_DGRAM: + *type = __WASI_FILETYPE_SOCKET_DGRAM; + break; + case SOCK_STREAM: + *type = __WASI_FILETYPE_SOCKET_STREAM; + break; + default: + return __WASI_EINVAL; + } + *rights_base = RIGHTS_SOCKET_BASE; + *rights_inheriting = RIGHTS_SOCKET_INHERITING; + } else if (S_ISFIFO(sb.st_mode)) { + *type = __WASI_FILETYPE_SOCKET_STREAM; + *rights_base = RIGHTS_SOCKET_BASE; + *rights_inheriting = RIGHTS_SOCKET_INHERITING; + } else { + return __WASI_EINVAL; + } + + // Strip off read/write bits based on the access mode. + switch (fcntl(fd, F_GETFL) & O_ACCMODE) { + case O_RDONLY: + *rights_base &= ~(__wasi_rights_t)__WASI_RIGHT_FD_WRITE; + break; + case O_WRONLY: + *rights_base &= ~(__wasi_rights_t)__WASI_RIGHT_FD_READ; + break; + } + return 0; +} + +// Returns the underlying file descriptor number of a file descriptor +// object. This function can only be applied to objects that have an +// underlying file descriptor number. +static int fd_number( + const struct fd_object *fo +) { + int number = fo->number; + assert(number >= 0 && "fd_number() called on virtual file descriptor"); + return number; +} + +// Lowers the reference count on a file descriptor object. When the +// reference count reaches zero, its resources are cleaned up. +static void fd_object_release( + struct fd_object *fo +) UNLOCKS(fo->refcount) { + if (refcount_release(&fo->refcount)) { + switch (fo->type) { + case __WASI_FILETYPE_DIRECTORY: + // For directories we may keep track of a DIR object. Calling + // closedir() on it also closes the underlying file descriptor. + mutex_destroy(&fo->directory.lock); + if (fo->directory.handle == NULL) { + close(fd_number(fo)); + } else { + closedir(fo->directory.handle); + } + break; + default: + close(fd_number(fo)); + break; + } + bh_free(fo); + } +} + +// Inserts an already existing file descriptor into the file descriptor +// table. +bool fd_table_insert_existing( + struct fd_table *ft, + __wasi_fd_t in, + int out +) { + __wasi_filetype_t type; + __wasi_rights_t rights_base, rights_inheriting; + if (fd_determine_type_rights(out, &type, &rights_base, &rights_inheriting) != + 0) + return false; + + struct fd_object *fo; + __wasi_errno_t error = fd_object_new(type, &fo); + if (error != 0) + return false; + fo->number = out; + if (type == __WASI_FILETYPE_DIRECTORY) { + mutex_init(&fo->directory.lock); + fo->directory.handle = NULL; + } + + // Grow the file descriptor table if needed. + rwlock_wrlock(&ft->lock); + if (!fd_table_grow(ft, in, 1)) { + rwlock_unlock(&ft->lock); + fd_object_release(fo); + return false; + } + + fd_table_attach(ft, in, fo, rights_base, rights_inheriting); + rwlock_unlock(&ft->lock); + return true; +} + +// Picks an unused slot from the file descriptor table. +static __wasi_fd_t fd_table_unused( + struct fd_table *ft +) REQUIRES_SHARED(ft->lock) { + assert(ft->size > ft->used && "File descriptor table has no free slots"); + for (;;) { + __wasi_fd_t fd = (__wasi_fd_t)random_uniform(ft->size); + if (ft->entries[fd].object == NULL) + return fd; + } +} + +// Inserts a file descriptor object into an unused slot of the file +// descriptor table. +static __wasi_errno_t fd_table_insert( + struct fd_table *ft, + struct fd_object *fo, + __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting, + __wasi_fd_t *out +) REQUIRES_UNLOCKED(ft->lock) UNLOCKS(fo->refcount) { + // Grow the file descriptor table if needed. + rwlock_wrlock(&ft->lock); + if (!fd_table_grow(ft, 0, 1)) { + rwlock_unlock(&ft->lock); + fd_object_release(fo); + return convert_errno(errno); + } + + *out = fd_table_unused(ft); + fd_table_attach(ft, *out, fo, rights_base, rights_inheriting); + rwlock_unlock(&ft->lock); + return 0; +} + +// Inserts a numerical file descriptor into the file descriptor table. +static __wasi_errno_t fd_table_insert_fd( + struct fd_table *ft, + int in, + __wasi_filetype_t type, + __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting, + __wasi_fd_t *out +) REQUIRES_UNLOCKED(ft->lock) { + struct fd_object *fo; + __wasi_errno_t error = fd_object_new(type, &fo); + if (error != 0) { + close(in); + return error; + } + fo->number = in; + if (type == __WASI_FILETYPE_DIRECTORY) { + mutex_init(&fo->directory.lock); + fo->directory.handle = NULL; + } + return fd_table_insert(ft, fo, rights_base, rights_inheriting, out); +} + +__wasi_errno_t wasmtime_ssp_fd_prestat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_prestats *prestats, +#endif + __wasi_fd_t fd, + __wasi_prestat_t *buf +) { + rwlock_rdlock(&prestats->lock); + struct fd_prestat *prestat; + __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat); + if (error != 0) { + rwlock_unlock(&prestats->lock); + return error; + } + + *buf = (__wasi_prestat_t) { + .pr_type = __WASI_PREOPENTYPE_DIR, + }; + + buf->u.dir.pr_name_len = strlen(prestat->dir); + + rwlock_unlock(&prestats->lock); + + return 0; +} + +__wasi_errno_t wasmtime_ssp_fd_prestat_dir_name( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_prestats *prestats, +#endif + __wasi_fd_t fd, + char *path, + size_t path_len +) { + rwlock_rdlock(&prestats->lock); + struct fd_prestat *prestat; + __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat); + if (error != 0) { + rwlock_unlock(&prestats->lock); + return error; + } + if (path_len != strlen(prestat->dir)) { + rwlock_unlock(&prestats->lock); + return EINVAL; + } + + bh_memcpy_s(path, path_len, prestat->dir, path_len); + + rwlock_unlock(&prestats->lock); + + return 0; +} + +__wasi_errno_t wasmtime_ssp_fd_close( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, + struct fd_prestats *prestats, +#endif + __wasi_fd_t fd +) { + // Don't allow closing a pre-opened resource. + // TODO: Eventually, we do want to permit this, once libpreopen in + // userspace is capable of removing entries from its tables as well. + { + rwlock_rdlock(&prestats->lock); + struct fd_prestat *prestat; + __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat); + rwlock_unlock(&prestats->lock); + if (error == 0) { + return __WASI_ENOTSUP; + } + } + + // Validate the file descriptor. + struct fd_table *ft = curfds; + rwlock_wrlock(&ft->lock); + struct fd_entry *fe; + __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe); + if (error != 0) { + rwlock_unlock(&ft->lock); + return error; + } + + // Remove it from the file descriptor table. + struct fd_object *fo; + fd_table_detach(ft, fd, &fo); + rwlock_unlock(&ft->lock); + fd_object_release(fo); + return 0; +} + +// Look up a file descriptor object in a locked file descriptor table +// and increases its reference count. +static __wasi_errno_t fd_object_get_locked( + struct fd_object **fo, + struct fd_table *ft, + __wasi_fd_t fd, + __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting +) TRYLOCKS_EXCLUSIVE(0, (*fo)->refcount) REQUIRES_EXCLUSIVE(ft->lock) { + // Test whether the file descriptor number is valid. + struct fd_entry *fe; + __wasi_errno_t error = + fd_table_get_entry(ft, fd, rights_base, rights_inheriting, &fe); + if (error != 0) + return error; + + // Increase the reference count on the file descriptor object. A copy + // of the rights are also stored, so callers can still access those if + // needed. + *fo = fe->object; + refcount_acquire(&(*fo)->refcount); + return 0; +} + +// Temporarily locks the file descriptor table to look up a file +// descriptor object, increases its reference count and drops the lock. +static __wasi_errno_t fd_object_get( + struct fd_table *curfds, + struct fd_object **fo, + __wasi_fd_t fd, + __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting +) TRYLOCKS_EXCLUSIVE(0, (*fo)->refcount) { + struct fd_table *ft = curfds; + rwlock_rdlock(&ft->lock); + __wasi_errno_t error = + fd_object_get_locked(fo, ft, fd, rights_base, rights_inheriting); + rwlock_unlock(&ft->lock); + return error; +} + +__wasi_errno_t wasmtime_ssp_fd_datasync( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd +) { + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_DATASYNC, 0); + if (error != 0) + return error; + +#if CONFIG_HAS_FDATASYNC + int ret = fdatasync(fd_number(fo)); +#else + int ret = fsync(fd_number(fo)); +#endif + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t wasmtime_ssp_fd_pread( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const __wasi_iovec_t *iov, + size_t iovcnt, + __wasi_filesize_t offset, + size_t *nread +) { + if (iovcnt == 0) + return __WASI_EINVAL; + + struct fd_object *fo; + __wasi_errno_t error = fd_object_get(curfds, + &fo, fd, __WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_SEEK, 0); + if (error != 0) + return error; + +#if CONFIG_HAS_PREADV + ssize_t len = + preadv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt, (off_t)offset); + fd_object_release(fo); + if (len < 0) + return convert_errno(errno); + *nread = (size_t)len; + return 0; +#else + if (iovcnt == 1) { + ssize_t len = pread(fd_number(fo), iov->buf, iov->buf_len, offset); + fd_object_release(fo); + if (len < 0) + return convert_errno(errno); + *nread = len; + return 0; + } else { + // Allocate a single buffer to fit all data. + size_t totalsize = 0; + for (size_t i = 0; i < iovcnt; ++i) + totalsize += iov[i].buf_len; + char *buf = bh_malloc(totalsize); + if (buf == NULL) { + fd_object_release(fo); + return __WASI_ENOMEM; + } + + // Perform a single read operation. + ssize_t len = pread(fd_number(fo), buf, totalsize, offset); + fd_object_release(fo); + if (len < 0) { + bh_free(buf); + return convert_errno(errno); + } + + // Copy data back to vectors. + size_t bufoff = 0; + for (size_t i = 0; i < iovcnt; ++i) { + if (bufoff + iov[i].buf_len < len) { + bh_memcpy_s(iov[i].buf, iov[i].buf_len, buf + bufoff, iov[i].buf_len); + bufoff += iov[i].buf_len; + } else { + bh_memcpy_s(iov[i].buf, iov[i].buf_len, buf + bufoff, len - bufoff); + break; + } + } + bh_free(buf); + *nread = len; + return 0; + } +#endif +} + +__wasi_errno_t wasmtime_ssp_fd_pwrite( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const __wasi_ciovec_t *iov, + size_t iovcnt, + __wasi_filesize_t offset, + size_t *nwritten +) { + if (iovcnt == 0) + return __WASI_EINVAL; + + struct fd_object *fo; + __wasi_errno_t error = fd_object_get(curfds, + &fo, fd, __WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FD_SEEK, 0); + if (error != 0) + return error; + + ssize_t len; +#if CONFIG_HAS_PWRITEV + len = pwritev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt, (off_t)offset); +#else + if (iovcnt == 1) { + len = pwrite(fd_number(fo), iov->buf, iov->buf_len, offset); + } else { + // Allocate a single buffer to fit all data. + size_t totalsize = 0; + for (size_t i = 0; i < iovcnt; ++i) + totalsize += iov[i].buf_len; + char *buf = bh_malloc(totalsize); + if (buf == NULL) { + fd_object_release(fo); + return __WASI_ENOMEM; + } + size_t bufoff = 0; + for (size_t i = 0; i < iovcnt; ++i) { + bh_memcpy_s(buf + bufoff, totalsize - bufoff, + iov[i].buf, iov[i].buf_len); + bufoff += iov[i].buf_len; + } + + // Perform a single write operation. + len = pwrite(fd_number(fo), buf, totalsize, offset); + bh_free(buf); + } +#endif + fd_object_release(fo); + if (len < 0) + return convert_errno(errno); + *nwritten = (size_t)len; + return 0; +} + +__wasi_errno_t wasmtime_ssp_fd_read( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const __wasi_iovec_t *iov, + size_t iovcnt, + size_t *nread +) { + struct fd_object *fo; + __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READ, 0); + if (error != 0) + return error; + + ssize_t len = readv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); + fd_object_release(fo); + if (len < 0) + return convert_errno(errno); + *nread = (size_t)len; + return 0; +} + +__wasi_errno_t wasmtime_ssp_fd_renumber( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, + struct fd_prestats *prestats, +#endif + __wasi_fd_t from, + __wasi_fd_t to +) { + // Don't allow renumbering over a pre-opened resource. + // TODO: Eventually, we do want to permit this, once libpreopen in + // userspace is capable of removing entries from its tables as well. + { + rwlock_rdlock(&prestats->lock); + struct fd_prestat *prestat; + __wasi_errno_t error = fd_prestats_get_entry(prestats, to, &prestat); + if (error != 0) { + error = fd_prestats_get_entry(prestats, from, &prestat); + } + rwlock_unlock(&prestats->lock); + if (error == 0) { + return __WASI_ENOTSUP; + } + } + + struct fd_table *ft = curfds; + rwlock_wrlock(&ft->lock); + struct fd_entry *fe_from; + __wasi_errno_t error = fd_table_get_entry(ft, from, 0, 0, &fe_from); + if (error != 0) { + rwlock_unlock(&ft->lock); + return error; + } + struct fd_entry *fe_to; + error = fd_table_get_entry(ft, to, 0, 0, &fe_to); + if (error != 0) { + rwlock_unlock(&ft->lock); + return error; + } + + struct fd_object *fo; + fd_table_detach(ft, to, &fo); + refcount_acquire(&fe_from->object->refcount); + fd_table_attach(ft, to, fe_from->object, fe_from->rights_base, + fe_from->rights_inheriting); + fd_object_release(fo); + + // Remove the old fd from the file descriptor table. + fd_table_detach(ft, from, &fo); + fd_object_release(fo); + --ft->used; + + rwlock_unlock(&ft->lock); + return 0; +} + +__wasi_errno_t wasmtime_ssp_fd_seek( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filedelta_t offset, + __wasi_whence_t whence, + __wasi_filesize_t *newoffset +) { + int nwhence; + switch (whence) { + case __WASI_WHENCE_CUR: + nwhence = SEEK_CUR; + break; + case __WASI_WHENCE_END: + nwhence = SEEK_END; + break; + case __WASI_WHENCE_SET: + nwhence = SEEK_SET; + break; + default: + return __WASI_EINVAL; + } + + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, + offset == 0 && whence == __WASI_WHENCE_CUR + ? __WASI_RIGHT_FD_TELL + : __WASI_RIGHT_FD_SEEK | __WASI_RIGHT_FD_TELL, + 0); + if (error != 0) + return error; + + off_t ret = lseek(fd_number(fo), offset, nwhence); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + *newoffset = (__wasi_filesize_t)ret; + return 0; +} + +__wasi_errno_t wasmtime_ssp_fd_tell( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filesize_t *newoffset +) { + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_TELL, 0); + if (error != 0) + return error; + + off_t ret = lseek(fd_number(fo), 0, SEEK_CUR); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + *newoffset = (__wasi_filesize_t)ret; + return 0; +} + +__wasi_errno_t wasmtime_ssp_fd_fdstat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_fdstat_t *buf +) { + struct fd_table *ft = curfds; + rwlock_rdlock(&ft->lock); + struct fd_entry *fe; + __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe); + if (error != 0) { + rwlock_unlock(&ft->lock); + return error; + } + + // Extract file descriptor type and rights. + struct fd_object *fo = fe->object; + *buf = (__wasi_fdstat_t){ + .fs_filetype = fo->type, + .fs_rights_base = fe->rights_base, + .fs_rights_inheriting = fe->rights_inheriting, + }; + + // Fetch file descriptor flags. + int ret; + switch (fo->type) { + default: + ret = fcntl(fd_number(fo), F_GETFL); + break; + } + rwlock_unlock(&ft->lock); + if (ret < 0) + return convert_errno(errno); + + if ((ret & O_APPEND) != 0) + buf->fs_flags |= __WASI_FDFLAG_APPEND; +#ifdef O_DSYNC + if ((ret & O_DSYNC) != 0) + buf->fs_flags |= __WASI_FDFLAG_DSYNC; +#endif + if ((ret & O_NONBLOCK) != 0) + buf->fs_flags |= __WASI_FDFLAG_NONBLOCK; +#ifdef O_RSYNC + if ((ret & O_RSYNC) != 0) + buf->fs_flags |= __WASI_FDFLAG_RSYNC; +#endif + if ((ret & O_SYNC) != 0) + buf->fs_flags |= __WASI_FDFLAG_SYNC; + return 0; +} + +__wasi_errno_t wasmtime_ssp_fd_fdstat_set_flags( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_fdflags_t fs_flags +) { + int noflags = 0; + if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) + noflags |= O_APPEND; + if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) +#ifdef O_DSYNC + noflags |= O_DSYNC; +#else + noflags |= O_SYNC; +#endif + if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0) + noflags |= O_NONBLOCK; + if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) +#ifdef O_RSYNC + noflags |= O_RSYNC; +#else + noflags |= O_SYNC; +#endif + if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) + noflags |= O_SYNC; + + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FDSTAT_SET_FLAGS, 0); + if (error != 0) + return error; + + int ret = fcntl(fd_number(fo), F_SETFL, noflags); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t wasmtime_ssp_fd_fdstat_set_rights( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_rights_t fs_rights_base, + __wasi_rights_t fs_rights_inheriting +) { + struct fd_table *ft = curfds; + rwlock_wrlock(&ft->lock); + struct fd_entry *fe; + __wasi_errno_t error = + fd_table_get_entry(ft, fd, fs_rights_base, fs_rights_inheriting, &fe); + if (error != 0) { + rwlock_unlock(&ft->lock); + return error; + } + + // Restrict the rights on the file descriptor. + fe->rights_base = fs_rights_base; + fe->rights_inheriting = fs_rights_inheriting; + rwlock_unlock(&ft->lock); + return 0; +} + +__wasi_errno_t wasmtime_ssp_fd_sync( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd +) { + struct fd_object *fo; + __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_SYNC, 0); + if (error != 0) + return error; + + int ret = fsync(fd_number(fo)); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t wasmtime_ssp_fd_write( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const __wasi_ciovec_t *iov, + size_t iovcnt, + size_t *nwritten +) { + struct fd_object *fo; + __wasi_errno_t error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_WRITE, 0); + if (error != 0) + return error; + + ssize_t len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); + fd_object_release(fo); + if (len < 0) + return convert_errno(errno); + *nwritten = (size_t)len; + return 0; +} + +__wasi_errno_t wasmtime_ssp_fd_advise( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filesize_t offset, + __wasi_filesize_t len, + __wasi_advice_t advice +) { +#ifdef POSIX_FADV_NORMAL + int nadvice; + switch (advice) { + case __WASI_ADVICE_DONTNEED: + nadvice = POSIX_FADV_DONTNEED; + break; + case __WASI_ADVICE_NOREUSE: + nadvice = POSIX_FADV_NOREUSE; + break; + case __WASI_ADVICE_NORMAL: + nadvice = POSIX_FADV_NORMAL; + break; + case __WASI_ADVICE_RANDOM: + nadvice = POSIX_FADV_RANDOM; + break; + case __WASI_ADVICE_SEQUENTIAL: + nadvice = POSIX_FADV_SEQUENTIAL; + break; + case __WASI_ADVICE_WILLNEED: + nadvice = POSIX_FADV_WILLNEED; + break; + default: + return __WASI_EINVAL; + } + + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_ADVISE, 0); + if (error != 0) + return error; + + int ret = posix_fadvise(fd_number(fo), (off_t)offset, (off_t)len, nadvice); + fd_object_release(fo); + if (ret != 0) + return convert_errno(ret); + return 0; +#else + // Advisory information can safely be ignored if unsupported. + switch (advice) { + case __WASI_ADVICE_DONTNEED: + case __WASI_ADVICE_NOREUSE: + case __WASI_ADVICE_NORMAL: + case __WASI_ADVICE_RANDOM: + case __WASI_ADVICE_SEQUENTIAL: + case __WASI_ADVICE_WILLNEED: + break; + default: + return __WASI_EINVAL; + } + + // At least check for file descriptor existence. + struct fd_table *ft = curfds; + rwlock_rdlock(&ft->lock); + struct fd_entry *fe; + __wasi_errno_t error = + fd_table_get_entry(ft, fd, __WASI_RIGHT_FD_ADVISE, 0, &fe); + rwlock_unlock(&ft->lock); + return error; +#endif +} + +__wasi_errno_t wasmtime_ssp_fd_allocate( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filesize_t offset, + __wasi_filesize_t len +) { + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_ALLOCATE, 0); + if (error != 0) + return error; + +#if CONFIG_HAS_POSIX_FALLOCATE + int ret = posix_fallocate(fd_number(fo), (off_t)offset, (off_t)len); +#else + // At least ensure that the file is grown to the right size. + // TODO(ed): See if this can somehow be implemented without any race + // conditions. We may end up shrinking the file right now. + struct stat sb; + int ret = fstat(fd_number(fo), &sb); + if (ret == 0 && sb.st_size < offset + len) + ret = ftruncate(fd_number(fo), offset + len); +#endif + + fd_object_release(fo); + if (ret != 0) + return convert_errno(ret); + return 0; +} + +// Reads the entire contents of a symbolic link, returning the contents +// in an allocated buffer. The allocated buffer is large enough to fit +// at least one extra byte, so the caller may append a trailing slash to +// it. This is needed by path_get(). +static char *readlinkat_dup( + int fd, + const char *path, + size_t *p_len +) { + char *buf = NULL; + size_t len = 32; + size_t len_org = len; + + for (;;) { + char *newbuf = bh_malloc((uint32)len); + + if (newbuf == NULL) { + if (buf) + bh_free(buf); + return NULL; + } + + if (buf != NULL) { + bh_memcpy_s(newbuf, (uint32)len, buf, (uint32)len_org); + bh_free(buf); + } + + buf = newbuf; + ssize_t ret = readlinkat(fd, path, buf, len); + if (ret < 0) { + bh_free(buf); + return NULL; + } + if ((size_t)ret + 1 < len) { + buf[ret] = '\0'; + *p_len = len; + return buf; + } + len_org = len; + len *= 2; + } +} + +// Lease to a directory, so a path underneath it can be accessed. +// +// This structure is used by system calls that operate on pathnames. In +// this environment, pathnames always consist of a pair of a file +// descriptor representing the directory where the lookup needs to start +// and the actual pathname string. +struct path_access { + int fd; // Directory file descriptor. + const char *path; // Pathname. + bool follow; // Whether symbolic links should be followed. + char *path_start; // Internal: pathname to free. + struct fd_object *fd_object; // Internal: directory file descriptor object. +}; + +// Creates a lease to a file descriptor and pathname pair. If the +// operating system does not implement Capsicum, it also normalizes the +// pathname to ensure the target path is placed underneath the +// directory. +static __wasi_errno_t path_get( + struct fd_table *curfds, + struct path_access *pa, + __wasi_fd_t fd, + __wasi_lookupflags_t flags, + const char *upath, + size_t upathlen, + __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting, + bool needs_final_component +) TRYLOCKS_EXCLUSIVE(0, pa->fd_object->refcount) { + char *path = str_nullterminate(upath, upathlen); + if (path == NULL) + return convert_errno(errno); + + // Fetch the directory file descriptor. + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, rights_base, rights_inheriting); + if (error != 0) { + bh_free(path); + return error; + } + +#if CONFIG_HAS_CAP_ENTER + // Rely on the kernel to constrain access to automatically constrain + // access to files stored underneath this directory. + pa->fd = fd_number(fo); + pa->path = pa->path_start = path; + pa->follow = (flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0; + pa->fd_object = fo; + return 0; +#else + // The implementation provides no mechanism to constrain lookups to a + // directory automatically. Emulate this logic by resolving the + // pathname manually. + + // Stack of directory file descriptors. Index 0 always corresponds + // with the directory provided to this function. Entering a directory + // causes a file descriptor to be pushed, while handling ".." entries + // causes an entry to be popped. Index 0 cannot be popped, as this + // would imply escaping the base directory. + int fds[128]; + fds[0] = fd_number(fo); + size_t curfd = 0; + + // Stack of pathname strings used for symlink expansion. By using a + // stack, there is no need to concatenate any pathname strings while + // expanding symlinks. + char *paths[32]; + char *paths_start[32]; + paths[0] = paths_start[0] = path; + size_t curpath = 0; + size_t expansions = 0; + char *symlink; + size_t symlink_len; + + for (;;) { + // Extract the next pathname component from 'paths[curpath]', null + // terminate it and store it in 'file'. 'ends_with_slashes' stores + // whether the pathname component is followed by one or more + // trailing slashes, as this requires it to be a directory. + char *file = paths[curpath]; + char *file_end = file + strcspn(file, "/"); + paths[curpath] = file_end + strspn(file_end, "/"); + bool ends_with_slashes = *file_end == '/'; + *file_end = '\0'; + + // Test for empty pathname strings and absolute paths. + if (file == file_end) { + error = ends_with_slashes ? __WASI_ENOTCAPABLE : __WASI_ENOENT; + goto fail; + } + + if (strcmp(file, ".") == 0) { + // Skip component. + } else if (strcmp(file, "..") == 0) { + // Pop a directory off the stack. + if (curfd == 0) { + // Attempted to go to parent directory of the directory file + // descriptor. + error = __WASI_ENOTCAPABLE; + goto fail; + } + close(fds[curfd--]); + } else if (curpath > 0 || *paths[curpath] != '\0' || + (ends_with_slashes && !needs_final_component)) { + // A pathname component whose name we're not interested in that is + // followed by a slash or is followed by other pathname + // components. In other words, a pathname component that must be a + // directory. First attempt to obtain a directory file descriptor + // for it. + int newdir = +#ifdef O_SEARCH + openat(fds[curfd], file, O_SEARCH | O_DIRECTORY | O_NOFOLLOW); +#else + openat(fds[curfd], file, O_RDONLY | O_DIRECTORY | O_NOFOLLOW); +#endif + if (newdir != -1) { + // Success. Push it onto the directory stack. + if (curfd + 1 == sizeof(fds) / sizeof(fds[0])) { + close(newdir); + error = __WASI_ENAMETOOLONG; + goto fail; + } + fds[++curfd] = newdir; + } else { + // Failed to open it. Attempt symlink expansion. + if (errno != ELOOP && errno != EMLINK && errno != ENOTDIR) { + error = convert_errno(errno); + goto fail; + } + symlink = readlinkat_dup(fds[curfd], file, &symlink_len); + if (symlink != NULL) + goto push_symlink; + + // readlink returns EINVAL if the path isn't a symlink. In that case, + // it's more informative to return ENOTDIR. + if (errno == EINVAL) + errno = ENOTDIR; + + error = convert_errno(errno); + goto fail; + } + } else { + // The final pathname component. Depending on whether it ends with + // a slash or the symlink-follow flag is set, perform symlink + // expansion. + if (ends_with_slashes || + (flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0) { + symlink = readlinkat_dup(fds[curfd], file, &symlink_len); + if (symlink != NULL) + goto push_symlink; + if (errno != EINVAL && errno != ENOENT) { + error = convert_errno(errno); + goto fail; + } + } + + // Not a symlink, meaning we're done. Return the filename, + // together with the directory containing this file. + // + // If the file was followed by a trailing slash, we must retain + // it, to ensure system calls properly return ENOTDIR. + // Unfortunately, this opens up a race condition, because this + // means that users of path_get() will perform symlink expansion a + // second time. There is nothing we can do to mitigate this, as + // far as I know. + if (ends_with_slashes) + *file_end = '/'; + pa->path = file; + pa->path_start = paths_start[0]; + goto success; + } + + if (*paths[curpath] == '\0') { + if (curpath == 0) { + // No further pathname components to process. We may end up here + // when called on paths like ".", "a/..", but also if the path + // had trailing slashes and the caller is not interested in the + // name of the pathname component. + bh_free(paths_start[0]); + pa->path = "."; + pa->path_start = NULL; + goto success; + } + + // Finished expanding symlink. Continue processing along the + // original path. + bh_free(paths_start[curpath--]); + } + continue; + + push_symlink: + // Prevent infinite loops by placing an upper limit on the number of + // symlink expansions. + if (++expansions == 128) { + bh_free(symlink); + error = __WASI_ELOOP; + goto fail; + } + + if (*paths[curpath] == '\0') { + // The original path already finished processing. Replace it by + // this symlink entirely. + bh_free(paths_start[curpath]); + } else if (curpath + 1 == sizeof(paths) / sizeof(paths[0])) { + // Too many nested symlinks. Stop processing. + bh_free(symlink); + error = __WASI_ELOOP; + goto fail; + } else { + // The original path still has components left. Retain the + // components that remain, so we can process them afterwards. + ++curpath; + } + + // Append a trailing slash to the symlink if the path leading up to + // it also contained one. Otherwise we would not throw ENOTDIR if + // the target is not a directory. + if (ends_with_slashes) + bh_strcat_s(symlink, (uint32)symlink_len, "/"); + paths[curpath] = paths_start[curpath] = symlink; + } + +success: + // Return the lease. Close all directories, except the one the caller + // needs to use. + for (size_t i = 1; i < curfd; ++i) + close(fds[i]); + pa->fd = fds[curfd]; + pa->follow = false; + pa->fd_object = fo; + return 0; + +fail: + // Failure. Free all resources. + for (size_t i = 1; i <= curfd; ++i) + close(fds[i]); + for (size_t i = 0; i <= curpath; ++i) + bh_free(paths_start[i]); + fd_object_release(fo); + return error; +#endif +} + +static __wasi_errno_t path_get_nofollow( + struct fd_table *curfds, + struct path_access *pa, + __wasi_fd_t fd, + const char *path, + size_t pathlen, + __wasi_rights_t rights_base, + __wasi_rights_t rights_inheriting, + bool needs_final_component +) TRYLOCKS_EXCLUSIVE(0, pa->fd_object->refcount) { + __wasi_lookupflags_t flags = 0; + return path_get(curfds, pa, fd, flags, path, pathlen, rights_base, rights_inheriting, + needs_final_component); +} + +static void path_put( + struct path_access *pa +) UNLOCKS(pa->fd_object->refcount) { + bh_free(pa->path_start); + if (fd_number(pa->fd_object) != pa->fd) + close(pa->fd); + fd_object_release(pa->fd_object); +} + +__wasi_errno_t wasmtime_ssp_path_create_directory( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const char *path, + size_t pathlen +) { + struct path_access pa; + __wasi_errno_t error = + path_get_nofollow(curfds, &pa, fd, path, pathlen, + __WASI_RIGHT_PATH_CREATE_DIRECTORY, 0, true); + if (error != 0) + return error; + + int ret = mkdirat(pa.fd, pa.path, 0777); + path_put(&pa); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t wasmtime_ssp_path_link( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t old_fd, + __wasi_lookupflags_t old_flags, + const char *old_path, + size_t old_path_len, + __wasi_fd_t new_fd, + const char *new_path, + size_t new_path_len +) { + struct path_access old_pa; + __wasi_errno_t error = path_get(curfds, &old_pa, old_fd, old_flags, old_path, old_path_len, + __WASI_RIGHT_PATH_LINK_SOURCE, 0, false); + if (error != 0) + return error; + + struct path_access new_pa; + error = path_get_nofollow(curfds, &new_pa, new_fd, new_path, new_path_len, + __WASI_RIGHT_PATH_LINK_TARGET, 0, true); + if (error != 0) { + path_put(&old_pa); + return error; + } + + int ret = linkat(old_pa.fd, old_pa.path, new_pa.fd, new_pa.path, + old_pa.follow ? AT_SYMLINK_FOLLOW : 0); + if (ret < 0 && errno == ENOTSUP && !old_pa.follow) { + // OS X doesn't allow creating hardlinks to symbolic links. + // Duplicate the symbolic link instead. + size_t target_len; + char *target = readlinkat_dup(old_pa.fd, old_pa.path, &target_len); + if (target != NULL) { + ret = symlinkat(target, new_pa.fd, new_pa.path); + bh_free(target); + } + } + path_put(&old_pa); + path_put(&new_pa); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t wasmtime_ssp_path_open( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t dirfd, + __wasi_lookupflags_t dirflags, + const char *path, + size_t pathlen, + __wasi_oflags_t oflags, + __wasi_rights_t fs_rights_base, + __wasi_rights_t fs_rights_inheriting, + __wasi_fdflags_t fs_flags, + __wasi_fd_t *fd +) { + // Rights that should be installed on the new file descriptor. + __wasi_rights_t rights_base = fs_rights_base; + __wasi_rights_t rights_inheriting = fs_rights_inheriting; + + // Which open() mode should be used to satisfy the needed rights. + bool read = + (rights_base & (__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_READDIR)) != 0; + bool write = + (rights_base & (__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_WRITE | + __WASI_RIGHT_FD_ALLOCATE | + __WASI_RIGHT_FD_FILESTAT_SET_SIZE)) != 0; + int noflags = write ? read ? O_RDWR : O_WRONLY : O_RDONLY; + + // Which rights are needed on the directory file descriptor. + __wasi_rights_t needed_base = __WASI_RIGHT_PATH_OPEN; + __wasi_rights_t needed_inheriting = rights_base | rights_inheriting; + + // Convert open flags. + if ((oflags & __WASI_O_CREAT) != 0) { + noflags |= O_CREAT; + needed_base |= __WASI_RIGHT_PATH_CREATE_FILE; + } + if ((oflags & __WASI_O_DIRECTORY) != 0) + noflags |= O_DIRECTORY; + if ((oflags & __WASI_O_EXCL) != 0) + noflags |= O_EXCL; + if ((oflags & __WASI_O_TRUNC) != 0) { + noflags |= O_TRUNC; + needed_base |= __WASI_RIGHT_PATH_FILESTAT_SET_SIZE; + } + + // Convert file descriptor flags. + if ((fs_flags & __WASI_FDFLAG_APPEND) != 0) + noflags |= O_APPEND; + if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) { +#ifdef O_DSYNC + noflags |= O_DSYNC; +#else + noflags |= O_SYNC; +#endif + needed_inheriting |= __WASI_RIGHT_FD_DATASYNC; + } + if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0) + noflags |= O_NONBLOCK; + if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) { +#ifdef O_RSYNC + noflags |= O_RSYNC; +#else + noflags |= O_SYNC; +#endif + needed_inheriting |= __WASI_RIGHT_FD_SYNC; + } + if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) { + noflags |= O_SYNC; + needed_inheriting |= __WASI_RIGHT_FD_SYNC; + } + if (write && (noflags & (O_APPEND | O_TRUNC)) == 0) + needed_inheriting |= __WASI_RIGHT_FD_SEEK; + + struct path_access pa; + __wasi_errno_t error = + path_get(curfds, &pa, dirfd, dirflags, path, pathlen, needed_base, needed_inheriting, + (oflags & __WASI_O_CREAT) != 0); + if (error != 0) + return error; + if (!pa.follow) + noflags |= O_NOFOLLOW; + + int nfd = openat(pa.fd, pa.path, noflags, 0666); + if (nfd < 0) { + int openat_errno = errno; + // Linux returns ENXIO instead of EOPNOTSUPP when opening a socket. + if (openat_errno == ENXIO) { + struct stat sb; + int ret = + fstatat(pa.fd, pa.path, &sb, pa.follow ? 0 : AT_SYMLINK_NOFOLLOW); + path_put(&pa); + return ret == 0 && S_ISSOCK(sb.st_mode) ? __WASI_ENOTSUP + : __WASI_ENXIO; + } + // Linux returns ENOTDIR instead of ELOOP when using O_NOFOLLOW|O_DIRECTORY + // on a symlink. + if (openat_errno == ENOTDIR && (noflags & (O_NOFOLLOW | O_DIRECTORY)) != 0) { + struct stat sb; + int ret = fstatat(pa.fd, pa.path, &sb, AT_SYMLINK_NOFOLLOW); + if (S_ISLNK(sb.st_mode)) { + path_put(&pa); + return __WASI_ELOOP; + } + (void)ret; + } + path_put(&pa); + // FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on + // a symlink. + if (!pa.follow && openat_errno == EMLINK) + return __WASI_ELOOP; + return convert_errno(openat_errno); + } + path_put(&pa); + + // Determine the type of the new file descriptor and which rights + // contradict with this type. + __wasi_filetype_t type; + __wasi_rights_t max_base, max_inheriting; + error = fd_determine_type_rights(nfd, &type, &max_base, &max_inheriting); + if (error != 0) { + close(nfd); + return error; + } + return fd_table_insert_fd(curfds, nfd, type, rights_base & max_base, + rights_inheriting & max_inheriting, fd); +} + +// Copies out directory entry metadata or filename, potentially +// truncating it in the process. +static void fd_readdir_put( + void *buf, + size_t bufsize, + size_t *bufused, + const void *elem, + size_t elemsize +) { + size_t bufavail = bufsize - *bufused; + if (elemsize > bufavail) + elemsize = bufavail; + bh_memcpy_s((char *)buf + *bufused, bufavail, elem, elemsize); + *bufused += elemsize; +} + +__wasi_errno_t wasmtime_ssp_fd_readdir( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + void *buf, + size_t nbyte, + __wasi_dircookie_t cookie, + size_t *bufused +) { + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READDIR, 0); + if (error != 0) { + return error; + } + + // Create a directory handle if none has been opened yet. + mutex_lock(&fo->directory.lock); + DIR *dp = fo->directory.handle; + if (dp == NULL) { + dp = fdopendir(fd_number(fo)); + if (dp == NULL) { + mutex_unlock(&fo->directory.lock); + fd_object_release(fo); + return convert_errno(errno); + } + fo->directory.handle = dp; + fo->directory.offset = __WASI_DIRCOOKIE_START; + } + + // Seek to the right position if the requested offset does not match + // the current offset. + if (fo->directory.offset != cookie) { + if (cookie == __WASI_DIRCOOKIE_START) + rewinddir(dp); + else + seekdir(dp, (long)cookie); + fo->directory.offset = cookie; + } + + *bufused = 0; + while (*bufused < nbyte) { + // Read the next directory entry. + errno = 0; + struct dirent *de = readdir(dp); + if (de == NULL) { + mutex_unlock(&fo->directory.lock); + fd_object_release(fo); + return errno == 0 || *bufused > 0 ? 0 : convert_errno(errno); + } + fo->directory.offset = (__wasi_dircookie_t)telldir(dp); + + // Craft a directory entry and copy that back. + size_t namlen = strlen(de->d_name); + __wasi_dirent_t cde = { + .d_next = fo->directory.offset, + .d_ino = de->d_ino, + .d_namlen = (uint32)namlen, + }; + switch (de->d_type) { + case DT_BLK: + cde.d_type = __WASI_FILETYPE_BLOCK_DEVICE; + break; + case DT_CHR: + cde.d_type = __WASI_FILETYPE_CHARACTER_DEVICE; + break; + case DT_DIR: + cde.d_type = __WASI_FILETYPE_DIRECTORY; + break; + case DT_FIFO: + cde.d_type = __WASI_FILETYPE_SOCKET_STREAM; + break; + case DT_LNK: + cde.d_type = __WASI_FILETYPE_SYMBOLIC_LINK; + break; + case DT_REG: + cde.d_type = __WASI_FILETYPE_REGULAR_FILE; + break; +#ifdef DT_SOCK + case DT_SOCK: + // Technically not correct, but good enough. + cde.d_type = __WASI_FILETYPE_SOCKET_STREAM; + break; +#endif + default: + cde.d_type = __WASI_FILETYPE_UNKNOWN; + break; + } + fd_readdir_put(buf, nbyte, bufused, &cde, sizeof(cde)); + fd_readdir_put(buf, nbyte, bufused, de->d_name, namlen); + } + mutex_unlock(&fo->directory.lock); + fd_object_release(fo); + return 0; +} + +__wasi_errno_t wasmtime_ssp_path_readlink( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const char *path, + size_t pathlen, + char *buf, + size_t bufsize, + size_t *bufused +) { + struct path_access pa; + __wasi_errno_t error = path_get_nofollow(curfds, + &pa, fd, path, pathlen, __WASI_RIGHT_PATH_READLINK, 0, false); + if (error != 0) + return error; + + // Linux requires that the buffer size is positive. whereas POSIX does + // not. Use a fake buffer to store the results if the size is zero. + char fakebuf[1]; + ssize_t len = readlinkat(pa.fd, pa.path, bufsize == 0 ? fakebuf : buf, + bufsize == 0 ? sizeof(fakebuf) : bufsize); + path_put(&pa); + if (len < 0) + return convert_errno(errno); + *bufused = (size_t)len < bufsize ? (size_t)len : bufsize; + return 0; +} + +__wasi_errno_t wasmtime_ssp_path_rename( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t old_fd, + const char *old_path, + size_t old_path_len, + __wasi_fd_t new_fd, + const char *new_path, + size_t new_path_len +) { + struct path_access old_pa; + __wasi_errno_t error = path_get_nofollow(curfds, &old_pa, old_fd, old_path, old_path_len, + __WASI_RIGHT_PATH_RENAME_SOURCE, 0, true); + if (error != 0) + return error; + + struct path_access new_pa; + error = path_get_nofollow(curfds, &new_pa, new_fd, new_path, new_path_len, + __WASI_RIGHT_PATH_RENAME_TARGET, 0, true); + if (error != 0) { + path_put(&old_pa); + return error; + } + + int ret = renameat(old_pa.fd, old_pa.path, new_pa.fd, new_pa.path); + path_put(&old_pa); + path_put(&new_pa); + if (ret < 0) { + return convert_errno(errno); + } + return 0; +} + +// Converts a POSIX stat structure to a CloudABI filestat structure. +static void convert_stat( + const struct stat *in, + __wasi_filestat_t *out +) { + *out = (__wasi_filestat_t){ + .st_dev = in->st_dev, + .st_ino = in->st_ino, + .st_nlink = (__wasi_linkcount_t)in->st_nlink, + .st_size = (__wasi_filesize_t)in->st_size, + .st_atim = convert_timespec(&in->st_atim), + .st_mtim = convert_timespec(&in->st_mtim), + .st_ctim = convert_timespec(&in->st_ctim), + }; +} + +__wasi_errno_t wasmtime_ssp_fd_filestat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filestat_t *buf +) { + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_GET, 0); + if (error != 0) + return error; + + int ret; + switch (fo->type) { + default: { + struct stat sb; + ret = fstat(fd_number(fo), &sb); + convert_stat(&sb, buf); + break; + } + } + buf->st_filetype = fo->type; + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +static void convert_timestamp( + __wasi_timestamp_t in, + struct timespec *out +) { + // Store sub-second remainder. + out->tv_nsec = (__syscall_slong_t)(in % 1000000000); + in /= 1000000000; + + // Clamp to the maximum in case it would overflow our system's time_t. + out->tv_sec = (time_t)in < NUMERIC_MAX(time_t) ? (time_t)in : NUMERIC_MAX(time_t); +} + +// Converts the provided timestamps and flags to a set of arguments for +// futimens() and utimensat(). +static void convert_utimens_arguments( + __wasi_timestamp_t st_atim, + __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags, + struct timespec *ts +) { + if ((fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0) { + ts[0].tv_nsec = UTIME_NOW; + } else if ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0) { + convert_timestamp(st_atim, &ts[0]); + } else { + ts[0].tv_nsec = UTIME_OMIT; + } + + if ((fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0) { + ts[1].tv_nsec = UTIME_NOW; + } else if ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0) { + convert_timestamp(st_mtim, &ts[1]); + } else { + ts[1].tv_nsec = UTIME_OMIT; + } +} + +__wasi_errno_t wasmtime_ssp_fd_filestat_set_size( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_filesize_t st_size +) { + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_SET_SIZE, 0); + if (error != 0) + return error; + + int ret = ftruncate(fd_number(fo), (off_t)st_size); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t wasmtime_ssp_fd_filestat_set_times( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_timestamp_t st_atim, + __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags +) { + if ((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW | + __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) != 0) + return __WASI_EINVAL; + + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_SET_TIMES, 0); + if (error != 0) + return error; + + struct timespec ts[2]; + convert_utimens_arguments(st_atim, st_mtim, fstflags, ts); + int ret = futimens(fd_number(fo), ts); + + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t wasmtime_ssp_path_filestat_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_lookupflags_t flags, + const char *path, + size_t pathlen, + __wasi_filestat_t *buf +) { + struct path_access pa; + __wasi_errno_t error = + path_get(curfds, &pa, fd, flags, path, pathlen, __WASI_RIGHT_PATH_FILESTAT_GET, 0, false); + if (error != 0) + return error; + + struct stat sb; + int ret = fstatat(pa.fd, pa.path, &sb, pa.follow ? 0 : AT_SYMLINK_NOFOLLOW); + path_put(&pa); + if (ret < 0) + return convert_errno(errno); + convert_stat(&sb, buf); + + // Convert the file type. In the case of sockets there is no way we + // can easily determine the exact socket type. + if (S_ISBLK(sb.st_mode)) + buf->st_filetype = __WASI_FILETYPE_BLOCK_DEVICE; + else if (S_ISCHR(sb.st_mode)) + buf->st_filetype = __WASI_FILETYPE_CHARACTER_DEVICE; + else if (S_ISDIR(sb.st_mode)) + buf->st_filetype = __WASI_FILETYPE_DIRECTORY; + else if (S_ISFIFO(sb.st_mode)) + buf->st_filetype = __WASI_FILETYPE_SOCKET_STREAM; + else if (S_ISLNK(sb.st_mode)) + buf->st_filetype = __WASI_FILETYPE_SYMBOLIC_LINK; + else if (S_ISREG(sb.st_mode)) + buf->st_filetype = __WASI_FILETYPE_REGULAR_FILE; + else if (S_ISSOCK(sb.st_mode)) + buf->st_filetype = __WASI_FILETYPE_SOCKET_STREAM; + return 0; +} + +__wasi_errno_t wasmtime_ssp_path_filestat_set_times( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + __wasi_lookupflags_t flags, + const char *path, + size_t pathlen, + __wasi_timestamp_t st_atim, + __wasi_timestamp_t st_mtim, + __wasi_fstflags_t fstflags +) { + if ((fstflags & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW | + __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW)) != 0) + return __WASI_EINVAL; + + struct path_access pa; + __wasi_errno_t error = path_get(curfds, + &pa, fd, flags, path, pathlen, __WASI_RIGHT_PATH_FILESTAT_SET_TIMES, 0, false); + if (error != 0) + return error; + + struct timespec ts[2]; + convert_utimens_arguments(st_atim, st_mtim, fstflags, ts); + int ret = utimensat(pa.fd, pa.path, ts, pa.follow ? 0 : AT_SYMLINK_NOFOLLOW); + + path_put(&pa); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t wasmtime_ssp_path_symlink( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + const char *old_path, + size_t old_path_len, + __wasi_fd_t fd, + const char *new_path, + size_t new_path_len +) { + char *target = str_nullterminate(old_path, old_path_len); + if (target == NULL) + return convert_errno(errno); + + struct path_access pa; + __wasi_errno_t error = path_get_nofollow(curfds, + &pa, fd, new_path, new_path_len, __WASI_RIGHT_PATH_SYMLINK, 0, true); + if (error != 0) { + bh_free(target); + return error; + } + + int ret = symlinkat(target, pa.fd, pa.path); + path_put(&pa); + bh_free(target); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t wasmtime_ssp_path_unlink_file( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const char *path, + size_t pathlen +) { + struct path_access pa; + __wasi_errno_t error = path_get_nofollow(curfds, + &pa, fd, path, pathlen, __WASI_RIGHT_PATH_UNLINK_FILE, 0, true); + if (error != 0) + return error; + + int ret = unlinkat(pa.fd, pa.path, 0); +#ifndef __linux__ + // Non-Linux implementations may return EPERM when attempting to remove a + // directory without REMOVEDIR. While that's what POSIX specifies, it's + // less useful. Adjust this to EISDIR. It doesn't matter that this is not + // atomic with the unlinkat, because if the file is removed and a directory + // is created before fstatat sees it, we're racing with that change anyway + // and unlinkat could have legitimately seen the directory if the race had + // turned out differently. + if (ret < 0 && errno == EPERM) { + struct stat statbuf; + if (fstatat(pa.fd, pa.path, &statbuf, AT_SYMLINK_NOFOLLOW) == 0 && + S_ISDIR(statbuf.st_mode)) { + errno = EISDIR; + } + } +#endif + path_put(&pa); + if (ret < 0) { + return convert_errno(errno); + } + return 0; +} + +__wasi_errno_t wasmtime_ssp_path_remove_directory( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t fd, + const char *path, + size_t pathlen +) { + struct path_access pa; + __wasi_errno_t error = path_get_nofollow(curfds, + &pa, fd, path, pathlen, __WASI_RIGHT_PATH_REMOVE_DIRECTORY, 0, true); + if (error != 0) + return error; + + int ret = unlinkat(pa.fd, pa.path, AT_REMOVEDIR); +#ifndef __linux__ + // POSIX permits either EEXIST or ENOTEMPTY when the directory is not empty. + // Map it to ENOTEMPTY. + if (ret < 0 && errno == EEXIST) { + errno = ENOTEMPTY; + } +#endif + path_put(&pa); + if (ret < 0) { + return convert_errno(errno); + } + return 0; +} + +__wasi_errno_t wasmtime_ssp_poll_oneoff( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + const __wasi_subscription_t *in, + __wasi_event_t *out, + size_t nsubscriptions, + size_t *nevents +) NO_LOCK_ANALYSIS { + // Sleeping. + if (nsubscriptions == 1 && in[0].type == __WASI_EVENTTYPE_CLOCK) { + out[0] = (__wasi_event_t){ + .userdata = in[0].userdata, + .type = in[0].type, + }; +#if CONFIG_HAS_CLOCK_NANOSLEEP + clockid_t clock_id; + if (convert_clockid(in[0].u.clock.clock_id, &clock_id)) { + struct timespec ts; + convert_timestamp(in[0].u.clock.timeout, &ts); + int ret = clock_nanosleep( + clock_id, + (in[0].u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) != 0 + ? TIMER_ABSTIME + : 0, + &ts, NULL); + if (ret != 0) + out[0].error = convert_errno(ret); + } else { + out[0].error = __WASI_ENOTSUP; + } +#else + switch (in[0].u.clock.clock_id) { + case __WASI_CLOCK_MONOTONIC: + if ((in[0].u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) != 0) { + // TODO(ed): Implement. + fputs("Unimplemented absolute sleep on monotonic clock\n", stderr); + out[0].error = __WASI_ENOSYS; + } else { + // Perform relative sleeps on the monotonic clock also using + // nanosleep(). This is incorrect, but good enough for now. + struct timespec ts; + convert_timestamp(in[0].u.clock.timeout, &ts); + nanosleep(&ts, NULL); + } + break; + case __WASI_CLOCK_REALTIME: + if ((in[0].u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) != 0) { + // Sleeping to an absolute point in time can only be done + // by waiting on a condition variable. + struct mutex mutex; + mutex_init(&mutex); + struct cond cond; + cond_init_realtime(&cond); + mutex_lock(&mutex); + cond_timedwait(&cond, &mutex, in[0].u.clock.timeout, true); + mutex_unlock(&mutex); + mutex_destroy(&mutex); + cond_destroy(&cond); + } else { + // Relative sleeps can be done using nanosleep(). + struct timespec ts; + convert_timestamp(in[0].u.clock.timeout, &ts); + nanosleep(&ts, NULL); + } + break; + default: + out[0].error = __WASI_ENOTSUP; + break; + } +#endif + *nevents = 1; + return 0; + } + + // Last option: call into poll(). This can only be done in case all + // subscriptions consist of __WASI_EVENTTYPE_FD_READ and + // __WASI_EVENTTYPE_FD_WRITE entries. There may be up to one + // __WASI_EVENTTYPE_CLOCK entry to act as a timeout. These are also + // the subscriptions generate by cloudlibc's poll() and select(). + struct fd_object **fos = bh_malloc((uint32)(nsubscriptions * sizeof(*fos))); + if (fos == NULL) + return __WASI_ENOMEM; + struct pollfd *pfds = bh_malloc((uint32)(nsubscriptions * sizeof(*pfds))); + if (pfds == NULL) { + bh_free(fos); + return __WASI_ENOMEM; + } + + // Convert subscriptions to pollfd entries. Increase the reference + // count on the file descriptors to ensure they remain valid across + // the call to poll(). + struct fd_table *ft = curfds; + rwlock_rdlock(&ft->lock); + *nevents = 0; + const __wasi_subscription_t *clock_subscription = NULL; + for (size_t i = 0; i < nsubscriptions; ++i) { + const __wasi_subscription_t *s = &in[i]; + switch (s->type) { + case __WASI_EVENTTYPE_FD_READ: + case __WASI_EVENTTYPE_FD_WRITE: { + __wasi_errno_t error = + fd_object_get_locked(&fos[i], ft, s->u.fd_readwrite.fd, + __WASI_RIGHT_POLL_FD_READWRITE, 0); + if (error == 0) { + // Proper file descriptor on which we can poll(). + pfds[i] = (struct pollfd){ + .fd = fd_number(fos[i]), + .events = s->type == __WASI_EVENTTYPE_FD_READ ? POLLRDNORM + : POLLWRNORM, + }; + } else { + // Invalid file descriptor or rights missing. + fos[i] = NULL; + pfds[i] = (struct pollfd){.fd = -1}; + out[(*nevents)++] = (__wasi_event_t){ + .userdata = s->userdata, + .error = error, + .type = s->type, + }; + } + break; + } + case __WASI_EVENTTYPE_CLOCK: + if (clock_subscription == NULL && + (s->u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) == 0) { + // Relative timeout. + fos[i] = NULL; + pfds[i] = (struct pollfd){.fd = -1}; + clock_subscription = s; + break; + } + // Fallthrough. + default: + // Unsupported event. + fos[i] = NULL; + pfds[i] = (struct pollfd){.fd = -1}; + out[(*nevents)++] = (__wasi_event_t){ + .userdata = s->userdata, + .error = __WASI_ENOSYS, + .type = s->type, + }; + break; + } + } + rwlock_unlock(&ft->lock); + + // Use a zero-second timeout in case we've already generated events in + // the loop above. + int timeout; + if (*nevents != 0) { + timeout = 0; + } else if (clock_subscription != NULL) { + __wasi_timestamp_t ts = clock_subscription->u.clock.timeout / 1000000; + timeout = ts > INT_MAX ? -1 : (int)ts; + } else { + timeout = -1; + } + int ret = poll(pfds, nsubscriptions, timeout); + + __wasi_errno_t error = 0; + if (ret == -1) { + error = convert_errno(errno); + } else if (ret == 0 && *nevents == 0 && clock_subscription != NULL) { + // No events triggered. Trigger the clock event. + out[(*nevents)++] = (__wasi_event_t){ + .userdata = clock_subscription->userdata, + .type = __WASI_EVENTTYPE_CLOCK, + }; + } else { + // Events got triggered. Don't trigger the clock event. + for (size_t i = 0; i < nsubscriptions; ++i) { + if (pfds[i].fd >= 0) { + __wasi_filesize_t nbytes = 0; + if (in[i].type == __WASI_EVENTTYPE_FD_READ) { + int l; + if (ioctl(fd_number(fos[i]), FIONREAD, &l) == 0) + nbytes = (__wasi_filesize_t)l; + } + if ((pfds[i].revents & POLLNVAL) != 0) { + // Bad file descriptor. This normally cannot occur, as + // referencing the file descriptor object will always ensure + // the descriptor is valid. Still, macOS may sometimes return + // this on FIFOs when reaching end-of-file. + out[(*nevents)++] = (__wasi_event_t){ + .userdata = in[i].userdata, +#ifdef __APPLE__ + .u.fd_readwrite.nbytes = nbytes, + .u.fd_readwrite.flags = __WASI_EVENT_FD_READWRITE_HANGUP, +#else + .error = __WASI_EBADF, +#endif + .type = in[i].type, + }; + } else if ((pfds[i].revents & POLLERR) != 0) { + // File descriptor is in an error state. + out[(*nevents)++] = (__wasi_event_t){ + .userdata = in[i].userdata, + .error = __WASI_EIO, + .type = in[i].type, + }; + } else if ((pfds[i].revents & POLLHUP) != 0) { + // End-of-file. + out[(*nevents)++] = (__wasi_event_t){ + .userdata = in[i].userdata, + .type = in[i].type, + .u.fd_readwrite.nbytes = nbytes, + .u.fd_readwrite.flags = __WASI_EVENT_FD_READWRITE_HANGUP, + }; + } else if ((pfds[i].revents & (POLLRDNORM | POLLWRNORM)) != 0) { + // Read or write possible. + out[(*nevents)++] = (__wasi_event_t){ + .userdata = in[i].userdata, + .type = in[i].type, + .u.fd_readwrite.nbytes = nbytes, + }; + } + } + } + } + + for (size_t i = 0; i < nsubscriptions; ++i) + if (fos[i] != NULL) + fd_object_release(fos[i]); + bh_free(fos); + bh_free(pfds); + return error; +} + +void wasmtime_ssp_proc_exit( + __wasi_exitcode_t rval +) { + _Exit((int32)rval); +} + +__wasi_errno_t wasmtime_ssp_proc_raise( + __wasi_signal_t sig +) { + static const int signals[] = { +#define X(v) [__WASI_##v] = v + X(SIGABRT), X(SIGALRM), X(SIGBUS), X(SIGCHLD), X(SIGCONT), X(SIGFPE), + X(SIGHUP), X(SIGILL), X(SIGINT), X(SIGKILL), X(SIGPIPE), X(SIGQUIT), + X(SIGSEGV), X(SIGSTOP), X(SIGSYS), X(SIGTERM), X(SIGTRAP), X(SIGTSTP), + X(SIGTTIN), X(SIGTTOU), X(SIGURG), X(SIGUSR1), X(SIGUSR2), X(SIGVTALRM), + X(SIGXCPU), X(SIGXFSZ), +#undef X + }; + if (sig >= sizeof(signals) / sizeof(signals[0]) || signals[sig] == 0) + return __WASI_EINVAL; + +#if CONFIG_TLS_USE_GSBASE + // TLS on OS X depends on installing a SIGSEGV handler. Reset SIGSEGV + // to the default action before raising. + if (sig == __WASI_SIGSEGV) { + struct sigaction sa = { + .sa_handler = SIG_DFL, + }; + sigemptyset(&sa.sa_mask); + sigaction(SIGSEGV, &sa, NULL); + } +#endif + + if (raise(signals[sig]) < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t wasmtime_ssp_random_get( + void *buf, + size_t nbyte +) { + random_buf(buf, nbyte); + return 0; +} + +__wasi_errno_t wasmtime_ssp_sock_recv( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + const __wasi_iovec_t *ri_data, + size_t ri_data_len, + __wasi_riflags_t ri_flags, + size_t *ro_datalen, + __wasi_roflags_t *ro_flags +) { + // Convert input to msghdr. + struct msghdr hdr = { + .msg_iov = (struct iovec *)ri_data, + .msg_iovlen = ri_data_len, + }; + int nflags = 0; + if ((ri_flags & __WASI_SOCK_RECV_PEEK) != 0) + nflags |= MSG_PEEK; + if ((ri_flags & __WASI_SOCK_RECV_WAITALL) != 0) + nflags |= MSG_WAITALL; + + struct fd_object *fo; + __wasi_errno_t error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_READ, 0); + if (error != 0) { + return error; + } + + ssize_t datalen = recvmsg(fd_number(fo), &hdr, nflags); + fd_object_release(fo); + if (datalen < 0) { + return convert_errno(errno); + } + + + // Convert msghdr to output. + *ro_datalen = (size_t)datalen; + *ro_flags = 0; + if ((hdr.msg_flags & MSG_TRUNC) != 0) + *ro_flags |= __WASI_SOCK_RECV_DATA_TRUNCATED; + return 0; +} + +__wasi_errno_t wasmtime_ssp_sock_send( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + const __wasi_ciovec_t *si_data, + size_t si_data_len, + __wasi_siflags_t si_flags, + size_t *so_datalen +) NO_LOCK_ANALYSIS { + // Convert input to msghdr. + struct msghdr hdr = { + .msg_iov = (struct iovec *)si_data, + .msg_iovlen = si_data_len, + }; + + // Attach file descriptors if present. + __wasi_errno_t error; + + // Send message. + struct fd_object *fo; + error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_WRITE, 0); + if (error != 0) + goto out; + ssize_t len = sendmsg(fd_number(fo), &hdr, 0); + fd_object_release(fo); + if (len < 0) { + error = convert_errno(errno); + } else { + *so_datalen = (size_t)len; + } + +out: + return error; +} + +__wasi_errno_t wasmtime_ssp_sock_shutdown( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct fd_table *curfds, +#endif + __wasi_fd_t sock, + __wasi_sdflags_t how +) { + int nhow; + switch (how) { + case __WASI_SHUT_RD: + nhow = SHUT_RD; + break; + case __WASI_SHUT_WR: + nhow = SHUT_WR; + break; + case __WASI_SHUT_RD | __WASI_SHUT_WR: + nhow = SHUT_RDWR; + break; + default: + return __WASI_EINVAL; + } + + struct fd_object *fo; + __wasi_errno_t error = + fd_object_get(curfds, &fo, sock, __WASI_RIGHT_SOCK_SHUTDOWN, 0); + if (error != 0) + return error; + + int ret = shutdown(fd_number(fo), nhow); + fd_object_release(fo); + if (ret < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t wasmtime_ssp_sched_yield(void) { + if (sched_yield() < 0) + return convert_errno(errno); + return 0; +} + +__wasi_errno_t wasmtime_ssp_args_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *argv_environ, +#endif + char **argv, + char *argv_buf +) { + for (size_t i = 0; i < argv_environ->argc; ++i) { + argv[i] = argv_buf + (argv_environ->argv[i] - argv_environ->argv_buf); + } + argv[argv_environ->argc] = NULL; + bh_memcpy_s(argv_buf, argv_environ->argv_buf_size, + argv_environ->argv_buf, argv_environ->argv_buf_size); + return __WASI_ESUCCESS; +} + +__wasi_errno_t wasmtime_ssp_args_sizes_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *argv_environ, +#endif + size_t *argc, + size_t *argv_buf_size +) { + *argc = argv_environ->argc; + *argv_buf_size = argv_environ->argv_buf_size; + return __WASI_ESUCCESS; +} + +__wasi_errno_t wasmtime_ssp_environ_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *argv_environ, +#endif + char **environ, + char *environ_buf +) { + for (size_t i = 0; i < argv_environ->environ_count; ++i) { + environ[i] = environ_buf + (argv_environ->environ[i] - argv_environ->environ_buf); + } + environ[argv_environ->environ_count] = NULL; + bh_memcpy_s(environ_buf, argv_environ->environ_buf_size, + argv_environ->environ_buf, argv_environ->environ_buf_size); + return __WASI_ESUCCESS; +} + +__wasi_errno_t wasmtime_ssp_environ_sizes_get( +#if !defined(WASMTIME_SSP_STATIC_CURFDS) + struct argv_environ_values *argv_environ, +#endif + size_t *environ_count, + size_t *environ_buf_size +) { + *environ_count = argv_environ->environ_count; + *environ_buf_size = argv_environ->environ_buf_size; + return __WASI_ESUCCESS; +} + +bool argv_environ_init(struct argv_environ_values *argv_environ, + const size_t *argv_offsets, size_t argv_offsets_len, + const char *argv_buf, size_t argv_buf_len, + const size_t *environ_offsets, size_t environ_offsets_len, + const char *environ_buf, size_t environ_buf_len) +{ + uint64 total_size; + size_t i; + + memset(argv_environ, 0, sizeof(struct argv_environ_values)); + + argv_environ->argc = argv_offsets_len; + argv_environ->argv_buf_size = argv_buf_len; + + total_size = sizeof(char *) * (uint64)argv_offsets_len; + if (total_size >= UINT32_MAX + || !(argv_environ->argv = bh_malloc((uint32)total_size))) + return false; + + + if (argv_buf_len >= UINT32_MAX + || !(argv_environ->argv_buf = bh_malloc((uint32)argv_buf_len))) + goto fail1; + + for (i = 0; i < argv_offsets_len; ++i) { + argv_environ->argv[i] = argv_environ->argv_buf + argv_offsets[i]; + } + bh_memcpy_s(argv_environ->argv_buf, (uint32)argv_buf_len, + argv_buf, (uint32)argv_buf_len); + + argv_environ->environ_count = environ_offsets_len; + argv_environ->environ_buf_size = environ_buf_len; + + total_size = sizeof(char *) * (uint64)environ_offsets_len; + if (total_size >= UINT32_MAX + || !(argv_environ->environ = bh_malloc((uint32)total_size))) + goto fail2; + + if (environ_buf_len >= UINT32_MAX + || !(argv_environ->environ_buf = bh_malloc((uint32)environ_buf_len))) + goto fail3; + + for (i = 0; i < environ_offsets_len; ++i) { + argv_environ->environ[i] = argv_environ->environ_buf + environ_offsets[i]; + } + bh_memcpy_s(argv_environ->environ_buf, (uint32)environ_buf_len, + environ_buf, (uint32)environ_buf_len); + + return true; + +fail3: + bh_free(argv_environ->environ); +fail2: + bh_free(argv_environ->argv_buf); +fail1: + bh_free(argv_environ->argv); + + memset(argv_environ, 0, sizeof(struct argv_environ_values)); + return false; +} + +void argv_environ_destroy(struct argv_environ_values *argv_environ) +{ + if (argv_environ->argv_buf) + bh_free(argv_environ->argv_buf); + if (argv_environ->argv) + bh_free(argv_environ->argv); + if (argv_environ->environ_buf) + bh_free(argv_environ->environ_buf); + if (argv_environ->environ) + bh_free(argv_environ->environ); +} + +void fd_table_destroy(struct fd_table *ft) +{ + if (ft->entries) { + for (uint32 i = 0; i < ft->size; i++) { + if (ft->entries[i].object != NULL) { + fd_object_release(ft->entries[i].object); + } + } + bh_free(ft->entries); + } +} + +void fd_prestats_destroy(struct fd_prestats *pt) +{ + if (pt->prestats) { + for (uint32 i = 0; i < pt->size; i++) { + if (pt->prestats[i].dir != NULL) { + bh_free((void*)pt->prestats[i].dir); + } + } + bh_free(pt->prestats); + } +} diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.h b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.h new file mode 100644 index 000000000..f4def4bc4 --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.h @@ -0,0 +1,62 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://github.com/CraneStation/wasmtime/blob/master/LICENSE for license information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/CraneStation/wasmtime/blob/master/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016-2018 Nuxi, https://nuxi.nl/ + +#ifndef POSIX_H +#define POSIX_H + +#include +#include + +#include "locking.h" + +struct fd_entry; +struct fd_prestat; +struct syscalls; + +struct fd_table { + struct rwlock lock; + struct fd_entry *entries; + size_t size; + size_t used; +}; + +struct fd_prestats { + struct rwlock lock; + struct fd_prestat *prestats; + size_t size; + size_t used; +}; + +struct argv_environ_values { + size_t argc; + size_t argv_buf_size; + char **argv; + char *argv_buf; + size_t environ_count; + size_t environ_buf_size; + char **environ; + char *environ_buf; +}; + +void fd_table_init(struct fd_table *); +bool fd_table_insert_existing(struct fd_table *, __wasi_fd_t, int); +void fd_prestats_init(struct fd_prestats *); +bool fd_prestats_insert(struct fd_prestats *, const char *, __wasi_fd_t); +bool argv_environ_init(struct argv_environ_values *, + const size_t *argv_offsets, size_t argv_offsets_len, + const char *argv_buf, size_t argv_buf_len, + const size_t *environ_offsets, size_t environ_offsets_len, + const char *environ_buf, size_t environ_buf_len); +void argv_environ_destroy(struct argv_environ_values *argv_environ); +void fd_table_destroy(struct fd_table *ft); +void fd_prestats_destroy(struct fd_prestats *pt); + +#endif diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/queue.h b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/queue.h new file mode 100644 index 000000000..c46190a85 --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/queue.h @@ -0,0 +1,92 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://github.com/CraneStation/wasmtime/blob/master/LICENSE for license information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/CraneStation/wasmtime/blob/master/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#ifndef QUEUE_H +#define QUEUE_H + +#include + +// LIST: Double-linked list. + +#define LIST_HEAD(name, type) \ + struct name { \ + struct type *l_first; \ + } +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ + struct { \ + struct type *l_next; \ + struct type **l_prev; \ + } + +#define LIST_FOREACH(var, head, field) \ + for ((var) = (head)->l_first; (var) != NULL; (var) = (var)->field.l_next) +#define LIST_INIT(head) \ + do { \ + (head)->l_first = NULL; \ + } while (0) +#define LIST_INSERT_HEAD(head, element, field) \ + do { \ + (element)->field.l_next = (head)->l_first; \ + if ((head)->l_first != NULL) \ + (head)->l_first->field.l_prev = &(element)->field.l_next; \ + (head)->l_first = (element); \ + (element)->field.l_prev = &(head)->l_first; \ + } while (0) +#define LIST_REMOVE(element, field) \ + do { \ + if ((element)->field.l_next != NULL) \ + (element)->field.l_next->field.l_prev = (element)->field.l_prev; \ + *(element)->field.l_prev = (element)->field.l_next; \ + } while (0) + +// TAILQ: Double-linked list with tail pointer. + +#define TAILQ_HEAD(name, type) \ + struct name { \ + struct type *t_first; \ + struct type **t_last; \ + } + +#define TAILQ_ENTRY(type) \ + struct { \ + struct type *t_next; \ + struct type **t_prev; \ + } + +#define TAILQ_EMPTY(head) ((head)->t_first == NULL) +#define TAILQ_FIRST(head) ((head)->t_first) +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = (head)->t_first; (var) != NULL; (var) = (var)->field.t_next) +#define TAILQ_INIT(head) \ + do { \ + (head)->t_first = NULL; \ + (head)->t_last = &(head)->t_first; \ + } while (0) +#define TAILQ_INSERT_TAIL(head, elm, field) \ + do { \ + (elm)->field.t_next = NULL; \ + (elm)->field.t_prev = (head)->t_last; \ + *(head)->t_last = (elm); \ + (head)->t_last = &(elm)->field.t_next; \ + } while (0) +#define TAILQ_REMOVE(head, element, field) \ + do { \ + if ((element)->field.t_next != NULL) \ + (element)->field.t_next->field.t_prev = (element)->field.t_prev; \ + else \ + (head)->t_last = (element)->field.t_prev; \ + *(element)->field.t_prev = (element)->field.t_next; \ + } while (0) + +#endif diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/random.c b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/random.c new file mode 100644 index 000000000..a3f17bbca --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/random.c @@ -0,0 +1,92 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://github.com/CraneStation/wasmtime/blob/master/LICENSE for license information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/CraneStation/wasmtime/blob/master/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "random.h" + +#if CONFIG_HAS_ARC4RANDOM_BUF + +void random_buf(void *buf, size_t len) { + arc4random_buf(buf, len); +} + +#elif CONFIG_HAS_GETRANDOM + +#include + +void random_buf(void *buf, size_t len) { + for (;;) { + ssize_t x = getrandom(buf, len, 0); + if (x < 0) { + if (errno == EINTR) + continue; + fprintf(stderr, "getrandom failed: %s", strerror(errno)); + abort(); + } + if (x == len) + return; + buf = (void *)((unsigned char *)buf + x); + len -= x; + } +} + +#else + +static int urandom; + +static void open_urandom(void) { + urandom = open("/dev/urandom", O_RDONLY); + if (urandom < 0) { + fputs("Failed to open /dev/urandom\n", stderr); + abort(); + } +} + +void random_buf(void *buf, size_t len) { + static pthread_once_t open_once = PTHREAD_ONCE_INIT; + pthread_once(&open_once, open_urandom); + + if ((size_t)read(urandom, buf, len) != len) { + fputs("Short read on /dev/urandom\n", stderr); + abort(); + } +} + +#endif + +// Calculates a random number within the range [0, upper - 1] without +// any modulo bias. +// +// The function below repeatedly obtains a random number from +// arc4random() until it lies within the range [2^k % upper, 2^k). As +// this range has length k * upper, we can safely obtain a number +// without any modulo bias. +uintmax_t random_uniform(uintmax_t upper) { + // Compute 2^k % upper + // == (2^k - upper) % upper + // == -upper % upper. + uintmax_t lower = -upper % upper; + for (;;) { + uintmax_t value; + random_buf(&value, sizeof(value)); + if (value >= lower) + return value % upper; + } +} diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/random.h b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/random.h new file mode 100644 index 000000000..d87a292cf --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/random.h @@ -0,0 +1,20 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://github.com/CraneStation/wasmtime/blob/master/LICENSE for license information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/CraneStation/wasmtime/blob/master/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#ifndef RANDOM_H +#define RANDOM_H + +#include + +void random_buf(void *, size_t); +uintmax_t random_uniform(uintmax_t); + +#endif diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/refcount.h b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/refcount.h new file mode 100644 index 000000000..0d516e2d1 --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/refcount.h @@ -0,0 +1,47 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://github.com/CraneStation/wasmtime/blob/master/LICENSE for license information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/CraneStation/wasmtime/blob/master/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#ifndef REFCOUNT_H +#define REFCOUNT_H + +#include +#include +#include + +#include "locking.h" + +// Simple reference counter. +struct LOCKABLE refcount { + atomic_uint count; +}; + +#define PRODUCES(...) LOCKS_SHARED(__VA_ARGS__) NO_LOCK_ANALYSIS +#define CONSUMES(...) UNLOCKS(__VA_ARGS__) NO_LOCK_ANALYSIS + +// Initialize the reference counter. +static void refcount_init(struct refcount *r, unsigned int count) PRODUCES(*r) { + atomic_init(&r->count, count); +} + +// Increment the reference counter. +static inline void refcount_acquire(struct refcount *r) PRODUCES(*r) { + atomic_fetch_add_explicit(&r->count, 1, memory_order_acquire); +} + +// Decrement the reference counter, returning whether the reference +// dropped to zero. +static inline bool refcount_release(struct refcount *r) CONSUMES(*r) { + int old = (int)atomic_fetch_sub_explicit(&r->count, 1, memory_order_release); + assert(old != 0 && "Reference count becoming negative"); + return old == 1; +} + +#endif diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/rights.h b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/rights.h new file mode 100644 index 000000000..69349e45c --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/rights.h @@ -0,0 +1,83 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://github.com/CraneStation/wasmtime/blob/master/LICENSE for license information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/CraneStation/wasmtime/blob/master/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#ifndef RIGHTS_H +#define RIGHTS_H + +#define RIGHTS_ALL \ + (__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_READ | \ + __WASI_RIGHT_FD_SEEK | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ + __WASI_RIGHT_FD_SYNC | __WASI_RIGHT_FD_TELL | __WASI_RIGHT_FD_WRITE | \ + __WASI_RIGHT_FD_ADVISE | __WASI_RIGHT_FD_ALLOCATE | \ + __WASI_RIGHT_PATH_CREATE_DIRECTORY | __WASI_RIGHT_PATH_CREATE_FILE | \ + __WASI_RIGHT_PATH_LINK_SOURCE | __WASI_RIGHT_PATH_LINK_TARGET | \ + __WASI_RIGHT_PATH_OPEN | __WASI_RIGHT_FD_READDIR | \ + __WASI_RIGHT_PATH_READLINK | __WASI_RIGHT_PATH_RENAME_SOURCE | \ + __WASI_RIGHT_PATH_RENAME_TARGET | __WASI_RIGHT_PATH_FILESTAT_GET | \ + __WASI_RIGHT_PATH_FILESTAT_SET_SIZE | \ + __WASI_RIGHT_PATH_FILESTAT_SET_TIMES | \ + __WASI_RIGHT_FD_FILESTAT_GET | __WASI_RIGHT_FD_FILESTAT_SET_TIMES | \ + __WASI_RIGHT_FD_FILESTAT_SET_SIZE | \ + __WASI_RIGHT_PATH_SYMLINK | __WASI_RIGHT_PATH_UNLINK_FILE | \ + __WASI_RIGHT_PATH_REMOVE_DIRECTORY | \ + __WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_SHUTDOWN) + +// Block and character device interaction is outside the scope of +// CloudABI. Simply allow everything. +#define RIGHTS_BLOCK_DEVICE_BASE RIGHTS_ALL +#define RIGHTS_BLOCK_DEVICE_INHERITING RIGHTS_ALL +#define RIGHTS_CHARACTER_DEVICE_BASE RIGHTS_ALL +#define RIGHTS_CHARACTER_DEVICE_INHERITING RIGHTS_ALL + +// Only allow directory operations on directories. Directories can only +// yield file descriptors to other directories and files. +#define RIGHTS_DIRECTORY_BASE \ + (__WASI_RIGHT_FD_FDSTAT_SET_FLAGS | __WASI_RIGHT_FD_SYNC | \ + __WASI_RIGHT_FD_ADVISE | __WASI_RIGHT_PATH_CREATE_DIRECTORY | \ + __WASI_RIGHT_PATH_CREATE_FILE | __WASI_RIGHT_PATH_LINK_SOURCE | \ + __WASI_RIGHT_PATH_LINK_TARGET | __WASI_RIGHT_PATH_OPEN | \ + __WASI_RIGHT_FD_READDIR | __WASI_RIGHT_PATH_READLINK | \ + __WASI_RIGHT_PATH_RENAME_SOURCE | __WASI_RIGHT_PATH_RENAME_TARGET | \ + __WASI_RIGHT_PATH_FILESTAT_GET | \ + __WASI_RIGHT_PATH_FILESTAT_SET_SIZE | \ + __WASI_RIGHT_PATH_FILESTAT_SET_TIMES | \ + __WASI_RIGHT_FD_FILESTAT_GET | __WASI_RIGHT_FD_FILESTAT_SET_TIMES | \ + __WASI_RIGHT_PATH_SYMLINK | __WASI_RIGHT_PATH_UNLINK_FILE | \ + __WASI_RIGHT_PATH_REMOVE_DIRECTORY | \ + __WASI_RIGHT_POLL_FD_READWRITE) +#define RIGHTS_DIRECTORY_INHERITING \ + (RIGHTS_DIRECTORY_BASE | RIGHTS_REGULAR_FILE_BASE) + +// Operations that apply to regular files. +#define RIGHTS_REGULAR_FILE_BASE \ + (__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_READ | \ + __WASI_RIGHT_FD_SEEK | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ + __WASI_RIGHT_FD_SYNC | __WASI_RIGHT_FD_TELL | __WASI_RIGHT_FD_WRITE | \ + __WASI_RIGHT_FD_ADVISE | __WASI_RIGHT_FD_ALLOCATE | \ + __WASI_RIGHT_FD_FILESTAT_GET | __WASI_RIGHT_FD_FILESTAT_SET_SIZE | \ + __WASI_RIGHT_FD_FILESTAT_SET_TIMES | __WASI_RIGHT_POLL_FD_READWRITE) +#define RIGHTS_REGULAR_FILE_INHERITING 0 + +// Operations that apply to sockets and socket pairs. +#define RIGHTS_SOCKET_BASE \ + (__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ + __WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FD_FILESTAT_GET | \ + __WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_SHUTDOWN) +#define RIGHTS_SOCKET_INHERITING RIGHTS_ALL + +// Operations that apply to TTYs. +#define RIGHTS_TTY_BASE \ + (__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \ + __WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FD_FILESTAT_GET | \ + __WASI_RIGHT_POLL_FD_READWRITE) +#define RIGHTS_TTY_INHERITING 0 + +#endif diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/signals.h b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/signals.h new file mode 100644 index 000000000..16f5d575c --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/signals.h @@ -0,0 +1,17 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://github.com/CraneStation/wasmtime/blob/master/LICENSE for license information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/CraneStation/wasmtime/blob/master/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#ifndef SIGNALS_H +#define SIGNALS_H + +void signals_init(void); + +#endif diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/str.c b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/str.c new file mode 100644 index 000000000..02a9518f4 --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/str.c @@ -0,0 +1,33 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://github.com/CraneStation/wasmtime/blob/master/LICENSE for license information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/CraneStation/wasmtime/blob/master/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#include "config.h" + +#include +#include +#include + +#include "str.h" + +char *str_nullterminate(const char *s, size_t len) { + // Copy string. + char *ret = strndup(s, len); + if (ret == NULL) + return NULL; + + // Ensure that it contains no null bytes within. + if (strlen(ret) != len) { + free(ret); + errno = EILSEQ; + return NULL; + } + return ret; +} diff --git a/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/str.h b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/str.h new file mode 100644 index 000000000..a9c5f226f --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/sandboxed-system-primitives/src/str.h @@ -0,0 +1,19 @@ +// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://github.com/CraneStation/wasmtime/blob/master/LICENSE for license information. +// +// Significant parts of this file are derived from cloudabi-utils. See +// https://github.com/CraneStation/wasmtime/blob/master/lib/wasi/sandboxed-system-primitives/src/LICENSE +// for license information. +// +// The upstream file contains the following copyright notice: +// +// Copyright (c) 2016 Nuxi, https://nuxi.nl/ + +#ifndef STR_H +#define STR_H + +#include "config.h" + +char *str_nullterminate(const char *, size_t); + +#endif diff --git a/core/iwasm/runtime/wasmtime-wasi-c/wasi.cmake b/core/iwasm/runtime/wasmtime-wasi-c/wasi.cmake new file mode 100644 index 000000000..533b6537c --- /dev/null +++ b/core/iwasm/runtime/wasmtime-wasi-c/wasi.cmake @@ -0,0 +1,12 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (WASI_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}) + +if (WASM_ENABLE_WASI EQUAL 1) + include_directories(${WASI_LIB_DIR}/sandboxed-system-primitives/include + ${WASI_LIB_DIR}/sandboxed-system-primitives/src + ) + file (GLOB_RECURSE source_all ${WASI_LIB_DIR}/sandboxed-system-primitives/*.c ) + set (WASI_LIB_SOURCE ${source_all}) +endif () diff --git a/core/shared-lib/coap/LICENSE b/core/shared-lib/coap/LICENSE deleted file mode 100644 index 031fe3669..000000000 --- a/core/shared-lib/coap/LICENSE +++ /dev/null @@ -1,38 +0,0 @@ -Contiki is licensed under the 3-clause BSD license. This license gives -everyone the right to use and distribute the code, either in binary or -source code format, as long as the copyright license is retained in -the source code. - -The copyright for different parts of the code is held by different -people and organizations, but the code is licensed under the same type -of license. The license text is: - - * Copyright (c) (Year), (Name of copyright holder) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/core/shared-lib/coap/Makefile b/core/shared-lib/coap/Makefile deleted file mode 100644 index efb3b6a14..000000000 --- a/core/shared-lib/coap/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -COAP_ROOT=${ZEPHYR_BASE}/subsys/aee/Beihai/runtime/utils/coap -subdir-ccflags-y += -I${COAP_ROOT}/er-coap -I${COAP_ROOT}/extension - -obj-y += er-coap/ -obj-y += extension/ diff --git a/core/shared-lib/coap/er-coap/LICENSE.md b/core/shared-lib/coap/er-coap/LICENSE.md new file mode 100644 index 000000000..f4b1a054c --- /dev/null +++ b/core/shared-lib/coap/er-coap/LICENSE.md @@ -0,0 +1,30 @@ +Copyright (c) (Year), (Name of copyright holder) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/core/shared-lib/coap/er-coap/Makefile b/core/shared-lib/coap/er-coap/Makefile deleted file mode 100644 index 1defea13e..000000000 --- a/core/shared-lib/coap/er-coap/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -obj-y += er-coap.o diff --git a/core/shared-lib/coap/er-coap/coap-constants.h b/core/shared-lib/coap/er-coap/coap-constants.h new file mode 100644 index 000000000..f73a5b950 --- /dev/null +++ b/core/shared-lib/coap/er-coap/coap-constants.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Collection of constants specified in the CoAP standard. + * \author + * Matthias Kovatsch + */ + +/** + * \addtogroup coap + * @{ + */ + +#ifndef COAP_CONSTANTS_H_ +#define COAP_CONSTANTS_H_ + +#define COAP_DEFAULT_PORT 5683 +#define COAP_DEFAULT_SECURE_PORT 5684 + +#define COAP_DEFAULT_MAX_AGE 60 +#define COAP_RESPONSE_TIMEOUT 3 +#define COAP_RESPONSE_RANDOM_FACTOR 1.5 +#define COAP_MAX_RETRANSMIT 4 + +#define COAP_HEADER_LEN 4 /* | version:0x03 type:0x0C tkl:0xF0 | code | mid:0x00FF | mid:0xFF00 | */ +#define COAP_TOKEN_LEN 8 /* The maximum number of bytes for the Token */ +#define COAP_ETAG_LEN 8 /* The maximum number of bytes for the ETag */ + +#define COAP_HEADER_VERSION_MASK 0xC0 +#define COAP_HEADER_VERSION_POSITION 6 +#define COAP_HEADER_TYPE_MASK 0x30 +#define COAP_HEADER_TYPE_POSITION 4 +#define COAP_HEADER_TOKEN_LEN_MASK 0x0F +#define COAP_HEADER_TOKEN_LEN_POSITION 0 + +#define COAP_HEADER_OPTION_DELTA_MASK 0xF0 +#define COAP_HEADER_OPTION_SHORT_LENGTH_MASK 0x0F + +/* CoAP message types */ +typedef enum { + COAP_TYPE_CON, /* confirmables */ + COAP_TYPE_NON, /* non-confirmables */ + COAP_TYPE_ACK, /* acknowledgements */ + COAP_TYPE_RST /* reset */ +} coap_message_type_t; + +/* CoAP request method codes */ +typedef enum { + COAP_GET = 1, + COAP_POST, + COAP_PUT, + COAP_DELETE +} coap_method_t; + +/* CoAP response codes */ +typedef enum { + NO_ERROR = 0, + + CREATED_2_01 = 65, /* CREATED */ + DELETED_2_02 = 66, /* DELETED */ + VALID_2_03 = 67, /* NOT_MODIFIED */ + CHANGED_2_04 = 68, /* CHANGED */ + CONTENT_2_05 = 69, /* OK */ + CONTINUE_2_31 = 95, /* CONTINUE */ + + BAD_REQUEST_4_00 = 128, /* BAD_REQUEST */ + UNAUTHORIZED_4_01 = 129, /* UNAUTHORIZED */ + BAD_OPTION_4_02 = 130, /* BAD_OPTION */ + FORBIDDEN_4_03 = 131, /* FORBIDDEN */ + NOT_FOUND_4_04 = 132, /* NOT_FOUND */ + METHOD_NOT_ALLOWED_4_05 = 133, /* METHOD_NOT_ALLOWED */ + NOT_ACCEPTABLE_4_06 = 134, /* NOT_ACCEPTABLE */ + PRECONDITION_FAILED_4_12 = 140, /* BAD_REQUEST */ + REQUEST_ENTITY_TOO_LARGE_4_13 = 141, /* REQUEST_ENTITY_TOO_LARGE */ + UNSUPPORTED_MEDIA_TYPE_4_15 = 143, /* UNSUPPORTED_MEDIA_TYPE */ + + INTERNAL_SERVER_ERROR_5_00 = 160, /* INTERNAL_SERVER_ERROR */ + NOT_IMPLEMENTED_5_01 = 161, /* NOT_IMPLEMENTED */ + BAD_GATEWAY_5_02 = 162, /* BAD_GATEWAY */ + SERVICE_UNAVAILABLE_5_03 = 163, /* SERVICE_UNAVAILABLE */ + GATEWAY_TIMEOUT_5_04 = 164, /* GATEWAY_TIMEOUT */ + PROXYING_NOT_SUPPORTED_5_05 = 165, /* PROXYING_NOT_SUPPORTED */ + + /* Erbium errors */ + MEMORY_ALLOCATION_ERROR = 192, + PACKET_SERIALIZATION_ERROR, + + /* Erbium hooks */ + MANUAL_RESPONSE, + PING_RESPONSE +} coap_status_t; + +/* CoAP header option numbers */ +typedef enum { + COAP_OPTION_IF_MATCH = 1, /* 0-8 B */ + COAP_OPTION_URI_HOST = 3, /* 1-255 B */ + COAP_OPTION_ETAG = 4, /* 1-8 B */ + COAP_OPTION_IF_NONE_MATCH = 5, /* 0 B */ + COAP_OPTION_OBSERVE = 6, /* 0-3 B */ + COAP_OPTION_URI_PORT = 7, /* 0-2 B */ + COAP_OPTION_LOCATION_PATH = 8, /* 0-255 B */ + COAP_OPTION_URI_PATH = 11, /* 0-255 B */ + COAP_OPTION_CONTENT_FORMAT = 12, /* 0-2 B */ + COAP_OPTION_MAX_AGE = 14, /* 0-4 B */ + COAP_OPTION_URI_QUERY = 15, /* 0-255 B */ + COAP_OPTION_ACCEPT = 17, /* 0-2 B */ + COAP_OPTION_LOCATION_QUERY = 20, /* 0-255 B */ + COAP_OPTION_BLOCK2 = 23, /* 1-3 B */ + COAP_OPTION_BLOCK1 = 27, /* 1-3 B */ + COAP_OPTION_SIZE2 = 28, /* 0-4 B */ + COAP_OPTION_PROXY_URI = 35, /* 1-1034 B */ + COAP_OPTION_PROXY_SCHEME = 39, /* 1-255 B */ + COAP_OPTION_SIZE1 = 60, /* 0-4 B */ +} coap_option_t; + +/* CoAP Content-Formats */ +typedef enum { + TEXT_PLAIN = 0, + TEXT_XML = 1, + TEXT_CSV = 2, + TEXT_HTML = 3, + IMAGE_GIF = 21, + IMAGE_JPEG = 22, + IMAGE_PNG = 23, + IMAGE_TIFF = 24, + AUDIO_RAW = 25, + VIDEO_RAW = 26, + APPLICATION_LINK_FORMAT = 40, + APPLICATION_XML = 41, + APPLICATION_OCTET_STREAM = 42, + APPLICATION_RDF_XML = 43, + APPLICATION_SOAP_XML = 44, + APPLICATION_ATOM_XML = 45, + APPLICATION_XMPP_XML = 46, + APPLICATION_EXI = 47, + APPLICATION_FASTINFOSET = 48, + APPLICATION_SOAP_FASTINFOSET = 49, + APPLICATION_JSON = 50, + APPLICATION_X_OBIX_BINARY = 51 +} coap_content_format_t; + +/** + * Resource flags for allowed methods and special functionalities. + */ +typedef enum { + NO_FLAGS = 0, + + /* methods to handle */ + METHOD_GET = (1 << 0), + METHOD_POST = (1 << 1), + METHOD_PUT = (1 << 2), + METHOD_DELETE = (1 << 3), + + /* special flags */ + HAS_SUB_RESOURCES = (1 << 4), + IS_SEPARATE = (1 << 5), + IS_OBSERVABLE = (1 << 6), + IS_PERIODIC = (1 << 7) +} coap_resource_flags_t; + +#endif /* COAP_CONSTANTS_H_ */ +/** @} */ diff --git a/core/shared-lib/coap/er-coap/er-coap-conf.h b/core/shared-lib/coap/er-coap/er-coap-conf.h deleted file mode 100755 index 8491fe75d..000000000 --- a/core/shared-lib/coap/er-coap/er-coap-conf.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -/** - * \file - * Collection of default configuration values. - * \author - * Matthias Kovatsch - */ - -#ifndef ER_COAP_CONF_H_ -#define ER_COAP_CONF_H_ - -/* Features that can be disabled to achieve smaller memory footprint */ -#define COAP_LINK_FORMAT_FILTERING 0 -#define COAP_PROXY_OPTION_PROCESSING 0 - -/* Listening port for the CoAP REST Engine */ -#ifndef COAP_SERVER_PORT -#define COAP_SERVER_PORT COAP_DEFAULT_PORT -#endif - -/* The number of concurrent messages that can be stored for retransmission in the transaction layer. */ -#ifndef COAP_MAX_OPEN_TRANSACTIONS -#define COAP_MAX_OPEN_TRANSACTIONS 4 -#endif /* COAP_MAX_OPEN_TRANSACTIONS */ - -/* Maximum number of failed request attempts before action */ -#ifndef COAP_MAX_ATTEMPTS -#define COAP_MAX_ATTEMPTS 4 -#endif /* COAP_MAX_ATTEMPTS */ - -/* Conservative size limit, as not all options have to be set at the same time. Check when Proxy-Uri option is used */ -#ifndef COAP_MAX_HEADER_SIZE /* Hdr CoF If-Match Obs Blo strings */ -#define COAP_MAX_HEADER_SIZE 512 -//(4 + COAP_TOKEN_LEN + 3 + 1 + COAP_ETAG_LEN + 4 + 4 + 30) /* 65 */ -#endif /* COAP_MAX_HEADER_SIZE */ - -/* Number of observer slots (each takes abot xxx bytes) */ -#ifndef COAP_MAX_OBSERVERS -#define COAP_MAX_OBSERVERS COAP_MAX_OPEN_TRANSACTIONS - 1 -#endif /* COAP_MAX_OBSERVERS */ - -/* Interval in notifies in which NON notifies are changed to CON notifies to check client. */ -#define COAP_OBSERVE_REFRESH_INTERVAL 20 - -#endif /* ER_COAP_CONF_H_ */ diff --git a/core/shared-lib/coap/er-coap/er-coap-constants.h b/core/shared-lib/coap/er-coap/er-coap-constants.h deleted file mode 100755 index 8ed6d903d..000000000 --- a/core/shared-lib/coap/er-coap/er-coap-constants.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -/** - * \file - * Collection of constants specified in the CoAP standard. - * \author - * Matthias Kovatsch - */ - -#ifndef ER_COAP_CONSTANTS_H_ -#define ER_COAP_CONSTANTS_H_ - -#define COAP_DEFAULT_PORT 5683 - -#define COAP_DEFAULT_MAX_AGE 60 -#define COAP_RESPONSE_TIMEOUT 3 -#define COAP_RESPONSE_RANDOM_FACTOR 1.5 -#define COAP_MAX_RETRANSMIT 4 - -#define COAP_HEADER_LEN 4 /* | version:0x03 type:0x0C tkl:0xF0 | code | mid:0x00FF | mid:0xFF00 | */ -#define COAP_TOKEN_LEN 8 /* The maximum number of bytes for the Token */ -#define COAP_ETAG_LEN 8 /* The maximum number of bytes for the ETag */ - -#define COAP_HEADER_VERSION_MASK 0xC0 -#define COAP_HEADER_VERSION_POSITION 6 -#define COAP_HEADER_TYPE_MASK 0x30 -#define COAP_HEADER_TYPE_POSITION 4 -#define COAP_HEADER_TOKEN_LEN_MASK 0x0F -#define COAP_HEADER_TOKEN_LEN_POSITION 0 - -#define COAP_HEADER_OPTION_DELTA_MASK 0xF0 -#define COAP_HEADER_OPTION_SHORT_LENGTH_MASK 0x0F - -/* CoAP message types */ -typedef enum { - COAP_TYPE_CON, /* confirmables */ - COAP_TYPE_NON, /* non-confirmables */ - COAP_TYPE_ACK, /* acknowledgements */ - COAP_TYPE_RST /* reset */ -} coap_message_type_t; - -/* CoAP request method codes */ -typedef enum { - COAP_GET = 1, COAP_POST, COAP_PUT, COAP_DELETE -} coap_method_t; - -/* CoAP response codes */ -typedef enum { - NO_ERROR = 0, - - CREATED_2_01 = 65, /* CREATED */ - DELETED_2_02 = 66, /* DELETED */ - VALID_2_03 = 67, /* NOT_MODIFIED */ - CHANGED_2_04 = 68, /* CHANGED */ - CONTENT_2_05 = 69, /* OK */ - CONTINUE_2_31 = 95, /* CONTINUE */ - - BAD_REQUEST_4_00 = 128, /* BAD_REQUEST */ - UNAUTHORIZED_4_01 = 129, /* UNAUTHORIZED */ - BAD_OPTION_4_02 = 130, /* BAD_OPTION */ - FORBIDDEN_4_03 = 131, /* FORBIDDEN */ - NOT_FOUND_4_04 = 132, /* NOT_FOUND */ - METHOD_NOT_ALLOWED_4_05 = 133, /* METHOD_NOT_ALLOWED */ - NOT_ACCEPTABLE_4_06 = 134, /* NOT_ACCEPTABLE */ - PRECONDITION_FAILED_4_12 = 140, /* BAD_REQUEST */ - REQUEST_ENTITY_TOO_LARGE_4_13 = 141, /* REQUEST_ENTITY_TOO_LARGE */ - UNSUPPORTED_MEDIA_TYPE_4_15 = 143, /* UNSUPPORTED_MEDIA_TYPE */ - - INTERNAL_SERVER_ERROR_5_00 = 160, /* INTERNAL_SERVER_ERROR */ - NOT_IMPLEMENTED_5_01 = 161, /* NOT_IMPLEMENTED */ - BAD_GATEWAY_5_02 = 162, /* BAD_GATEWAY */ - SERVICE_UNAVAILABLE_5_03 = 163, /* SERVICE_UNAVAILABLE */ - GATEWAY_TIMEOUT_5_04 = 164, /* GATEWAY_TIMEOUT */ - PROXYING_NOT_SUPPORTED_5_05 = 165, /* PROXYING_NOT_SUPPORTED */ - - /* Erbium errors */ - MEMORY_ALLOCATION_ERROR = 192, PACKET_SERIALIZATION_ERROR, - - /* Erbium hooks */ - MANUAL_RESPONSE, PING_RESPONSE -} coap_status_t; - -/* CoAP header option numbers */ -typedef enum { - COAP_OPTION_IF_MATCH = 1, /* 0-8 B */ - COAP_OPTION_URI_HOST = 3, /* 1-255 B */ - COAP_OPTION_ETAG = 4, /* 1-8 B */ - COAP_OPTION_IF_NONE_MATCH = 5, /* 0 B */ - COAP_OPTION_OBSERVE = 6, /* 0-3 B */ - COAP_OPTION_URI_PORT = 7, /* 0-2 B */ - COAP_OPTION_LOCATION_PATH = 8, /* 0-255 B */ - COAP_OPTION_URI_PATH = 11, /* 0-255 B */ - COAP_OPTION_CONTENT_FORMAT = 12, /* 0-2 B */ - COAP_OPTION_MAX_AGE = 14, /* 0-4 B */ - COAP_OPTION_URI_QUERY = 15, /* 0-255 B */ - COAP_OPTION_ACCEPT = 17, /* 0-2 B */ - COAP_OPTION_LOCATION_QUERY = 20, /* 0-255 B */ - COAP_OPTION_BLOCK2 = 23, /* 1-3 B */ - COAP_OPTION_BLOCK1 = 27, /* 1-3 B */ - COAP_OPTION_SIZE2 = 28, /* 0-4 B */ - COAP_OPTION_PROXY_URI = 35, /* 1-1034 B */ - COAP_OPTION_PROXY_SCHEME = 39, /* 1-255 B */ - COAP_OPTION_SIZE1 = 60, /* 0-4 B */ -} coap_option_t; - -/* CoAP Content-Formats */ -typedef enum { - TEXT_PLAIN = 0, - TEXT_XML = 1, - TEXT_CSV = 2, - TEXT_HTML = 3, - IMAGE_GIF = 21, - IMAGE_JPEG = 22, - IMAGE_PNG = 23, - IMAGE_TIFF = 24, - AUDIO_RAW = 25, - VIDEO_RAW = 26, - APPLICATION_LINK_FORMAT = 40, - APPLICATION_XML = 41, - APPLICATION_OCTET_STREAM = 42, - APPLICATION_RDF_XML = 43, - APPLICATION_SOAP_XML = 44, - APPLICATION_ATOM_XML = 45, - APPLICATION_XMPP_XML = 46, - APPLICATION_EXI = 47, - APPLICATION_FASTINFOSET = 48, - APPLICATION_SOAP_FASTINFOSET = 49, - APPLICATION_JSON = 50, - APPLICATION_X_OBIX_BINARY = 51 -} coap_content_format_t; - -#endif /* ER_COAP_CONSTANTS_H_ */ diff --git a/core/shared-lib/coap/er-coap/er-coap.c b/core/shared-lib/coap/er-coap/er-coap.c deleted file mode 100755 index 88e61836a..000000000 --- a/core/shared-lib/coap/er-coap/er-coap.c +++ /dev/null @@ -1,1131 +0,0 @@ -/* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -/** - * \file - * An implementation of the Constrained Application Protocol (RFC). - * \author - * Matthias Kovatsch - */ - -#include -#include -//#include "contiki.h" -//#include "sys/cc.h" -//#include "contiki-net.h" - -#include "bh_common.h" -#include "er-coap.h" -/*#include "er-coap-transactions.h"*/ - -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif - -/*---------------------------------------------------------------------------*/ -/*- Variables ---------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -static uint16_t current_mid = 0; - -coap_status_t erbium_status_code = NO_ERROR; -char *coap_error_message = ""; -/*---------------------------------------------------------------------------*/ -/*- Local helper functions --------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -uint16_t coap_log_2(uint16_t value) -{ - uint16_t result = 0; - - do { - value = value >> 1; - result++; - } while (value); - - return result ? result - 1 : result; -} -/*---------------------------------------------------------------------------*/ -uint32_t coap_parse_int_option(uint8_t *bytes, size_t length) -{ - uint32_t var = 0; - int i = 0; - - while (i < length) { - var <<= 8; - var |= bytes[i++]; - } - return var; -} -/*---------------------------------------------------------------------------*/ -static uint8_t coap_option_nibble(unsigned int value) -{ - if (value < 13) { - return value; - } else if (value <= 0xFF + 13) { - return 13; - } else { - return 14; - } -} -/*---------------------------------------------------------------------------*/ -static size_t coap_set_option_header(unsigned int delta, size_t length, - uint8_t *buffer) -{ - size_t written = 0; - - buffer[0] = coap_option_nibble(delta) << 4 | coap_option_nibble(length); - - /* avoids code duplication without function overhead */ - unsigned int *x = δ - - do { - if (*x > 268) { - buffer[++written] = (*x - 269) >> 8; - buffer[++written] = (*x - 269); - } else if (*x > 12) { - buffer[++written] = (*x - 13); - } - } while (x != (unsigned int*) &length && (x = (unsigned int*) &length)); - - PRINTF("WRITTEN %u B opt header\n", 1 + written); - - return ++written; -} -/*---------------------------------------------------------------------------*/ -size_t coap_serialize_int_option(unsigned int number, - unsigned int current_number, uint8_t *buffer, uint32_t value) -{ - size_t i = 0; - - if (0xFF000000 & value) { - ++i; - } - if (0xFFFF0000 & value) { - ++i; - } - if (0xFFFFFF00 & value) { - ++i; - } - // if(0xFFFFFFFF & value) { - ++i; - // } - PRINTF("OPTION %u (delta %u, len %u)\n", number, number - current_number, - i); - - i = coap_set_option_header(number - current_number, i, buffer); - - if (0xFF000000 & value) { - buffer[i++] = (uint8_t)(value >> 24); - } - if (0xFFFF0000 & value) { - buffer[i++] = (uint8_t)(value >> 16); - } - if (0xFFFFFF00 & value) { - buffer[i++] = (uint8_t)(value >> 8); - } - // if(0xFFFFFFFF & value) { - buffer[i++] = (uint8_t)(value); - // } - return i; -} -/*---------------------------------------------------------------------------*/ -size_t coap_serialize_array_option(unsigned int number, - unsigned int current_number, uint8_t *buffer, uint8_t *array, - size_t length, char split_char) -{ - size_t i = 0; - - PRINTF("ARRAY type %u, len %u, full [%.*s]\n", number, length, length, - array); - - if (split_char != '\0') { - int j; - uint8_t *part_start = array; - uint8_t *part_end = NULL; - size_t temp_length; - - for (j = 0; j <= length + 1; ++j) { - PRINTF("STEP %u/%u (%c)\n", j, length, array[j]); - if (array[j] == split_char || j == length) { - part_end = array + j; - temp_length = part_end - part_start; - - i += coap_set_option_header(number - current_number, - temp_length, &buffer[i]); - bh_memcpy_s(&buffer[i], temp_length, part_start, temp_length); - i += temp_length; - - PRINTF("OPTION type %u, delta %u, len %u, part [%.*s]\n", number, - number - current_number, i, temp_length, part_start); - - ++j; /* skip the splitter */ - current_number = number; - part_start = array + j; - } - } /* for */ - } else { - i += coap_set_option_header(number - current_number, length, - &buffer[i]); - bh_memcpy_s(&buffer[i], length, array, length); - i += length; - - PRINTF("OPTION type %u, delta %u, len %u\n", number, - number - current_number, length); - } - - return i; -} -/*---------------------------------------------------------------------------*/ -void coap_merge_multi_option(char **dst, size_t *dst_len, uint8_t *option, - size_t option_len, char separator) -{ - /* merge multiple options */ - if (*dst_len > 0) { - /* dst already contains an option: concatenate */ - (*dst)[*dst_len] = separator; - *dst_len += 1; - - /* memmove handles 2-byte option headers */ - memmove((*dst) + (*dst_len), option, option_len); - - *dst_len += option_len; - } else { - /* dst is empty: set to option */ - *dst = (char *) option; - *dst_len = option_len; - } -} -/*---------------------------------------------------------------------------*/ -#if 0 -static int -coap_get_variable(const char *buffer, size_t length, const char *name, - const char **output) -{ - const char *start = NULL; - const char *end = NULL; - const char *value_end = NULL; - size_t name_len = 0; - - /*initialize the output buffer first */ - *output = 0; - - name_len = strlen(name); - end = buffer + length; - - for(start = buffer; start + name_len < end; ++start) { - if((start == buffer || start[-1] == '&') && start[name_len] == '=' - && strncmp(name, start, name_len) == 0) { - - /* Point start to variable value */ - start += name_len + 1; - - /* Point end to the end of the value */ - value_end = (const char *)memchr(start, '&', end - start); - if(value_end == NULL) { - value_end = end; - } - *output = start; - - return value_end - start; - } - } - return 0; -} -#endif -/*---------------------------------------------------------------------------*/ -/*- Internal API ------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -uint16_t coap_get_mid() -{ - return ++current_mid; -} - -/*---------------------------------------------------------------------------*/ -void coap_init_message(void *packet, coap_message_type_t type, uint8_t code, - uint16_t mid) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - /* Important thing */ - memset(coap_pkt, 0, sizeof(coap_packet_t)); - - coap_pkt->type = type; - coap_pkt->code = code; - coap_pkt->mid = mid; -} -#if 0 -/*---------------------------------------------------------------------------*/ -size_t -coap_serialize_message(void *packet, uint8_t *buffer) -{ - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - uint8_t *option; - unsigned int current_number = 0; - - /* Initialize */ - coap_pkt->buffer = buffer; - coap_pkt->version = 1; - - PRINTF("-Serializing MID %u to %p, ", coap_pkt->mid, coap_pkt->buffer); - - /* set header fields */ - coap_pkt->buffer[0] = 0x00; - coap_pkt->buffer[0] |= COAP_HEADER_VERSION_MASK - & (coap_pkt->version) << COAP_HEADER_VERSION_POSITION; - coap_pkt->buffer[0] |= COAP_HEADER_TYPE_MASK - & (coap_pkt->type) << COAP_HEADER_TYPE_POSITION; - coap_pkt->buffer[0] |= COAP_HEADER_TOKEN_LEN_MASK - & (coap_pkt->token_len) << COAP_HEADER_TOKEN_LEN_POSITION; - coap_pkt->buffer[1] = coap_pkt->code; - coap_pkt->buffer[2] = (uint8_t)((coap_pkt->mid) >> 8); - coap_pkt->buffer[3] = (uint8_t)(coap_pkt->mid); - - /* empty packet, dont need to do more stuff */ - if(!coap_pkt->code) { - PRINTF("-Done serializing empty message at %p-\n", option); - return 4; - } - - /* set Token */ - PRINTF("Token (len %u)", coap_pkt->token_len); - option = coap_pkt->buffer + COAP_HEADER_LEN; - for(current_number = 0; current_number < coap_pkt->token_len; - ++current_number) { - PRINTF(" %02X", coap_pkt->token[current_number]); - *option = coap_pkt->token[current_number]; - ++option; - } - PRINTF("-\n"); - - /* Serialize options */ - current_number = 0; - - PRINTF("-Serializing options at %p-\n", option); - - /* The options must be serialized in the order of their number */ - COAP_SERIALIZE_BYTE_OPTION(COAP_OPTION_IF_MATCH, if_match, "If-Match"); - COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_HOST, uri_host, '\0', - "Uri-Host"); - COAP_SERIALIZE_BYTE_OPTION(COAP_OPTION_ETAG, etag, "ETag"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_IF_NONE_MATCH, - content_format - - coap_pkt-> - content_format /* hack to get a zero field */, - "If-None-Match"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_OBSERVE, observe, "Observe"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_URI_PORT, uri_port, "Uri-Port"); - COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_LOCATION_PATH, location_path, '/', - "Location-Path"); - COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_PATH, uri_path, '/', - "Uri-Path"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_CONTENT_FORMAT, content_format, - "Content-Format"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_MAX_AGE, max_age, "Max-Age"); - COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_QUERY, uri_query, '&', - "Uri-Query"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_ACCEPT, accept, "Accept"); - COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_LOCATION_QUERY, location_query, - '&', "Location-Query"); - COAP_SERIALIZE_BLOCK_OPTION(COAP_OPTION_BLOCK2, block2, "Block2"); - COAP_SERIALIZE_BLOCK_OPTION(COAP_OPTION_BLOCK1, block1, "Block1"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_SIZE2, size2, "Size2"); - COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_PROXY_URI, proxy_uri, '\0', - "Proxy-Uri"); - COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_PROXY_SCHEME, proxy_scheme, '\0', - "Proxy-Scheme"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_SIZE1, size1, "Size1"); - - PRINTF("-Done serializing at %p----\n", option); - - /* Pack payload */ - if((option - coap_pkt->buffer) <= COAP_MAX_HEADER_SIZE) { - /* Payload marker */ - if(coap_pkt->payload_len) { - *option = 0xFF; - ++option; - } - memmove(option, coap_pkt->payload, coap_pkt->payload_len); - } else { - /* an error occurred: caller must check for !=0 */ - coap_pkt->buffer = NULL; - coap_error_message = "Serialized header exceeds COAP_MAX_HEADER_SIZE"; - return 0; - } - - PRINTF("-Done %u B (header len %u, payload len %u)-\n", - coap_pkt->payload_len + option - buffer, option - buffer, - coap_pkt->payload_len); - - PRINTF("Dump [0x%02X %02X %02X %02X %02X %02X %02X %02X]\n", - coap_pkt->buffer[0], - coap_pkt->buffer[1], - coap_pkt->buffer[2], - coap_pkt->buffer[3], - coap_pkt->buffer[4], - coap_pkt->buffer[5], coap_pkt->buffer[6], coap_pkt->buffer[7] - ); - - return (option - buffer) + coap_pkt->payload_len; /* packet length */ -} - -/*---------------------------------------------------------------------------*/ -coap_status_t -coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) -{ - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - /* initialize packet */ - memset(coap_pkt, 0, sizeof(coap_packet_t)); - - /* pointer to packet bytes */ - coap_pkt->buffer = data; - - /* parse header fields */ - coap_pkt->version = (COAP_HEADER_VERSION_MASK & coap_pkt->buffer[0]) - >> COAP_HEADER_VERSION_POSITION; - coap_pkt->type = (COAP_HEADER_TYPE_MASK & coap_pkt->buffer[0]) - >> COAP_HEADER_TYPE_POSITION; - coap_pkt->token_len = - MIN(COAP_TOKEN_LEN, - (COAP_HEADER_TOKEN_LEN_MASK & coap_pkt-> - buffer[0]) >> COAP_HEADER_TOKEN_LEN_POSITION); - coap_pkt->code = coap_pkt->buffer[1]; - coap_pkt->mid = coap_pkt->buffer[2] << 8 | coap_pkt->buffer[3]; - - if(coap_pkt->version != 1) { - coap_error_message = "CoAP version must be 1"; - return BAD_REQUEST_4_00; - } - - uint8_t *current_option = data + COAP_HEADER_LEN; - - bh_memcpy_s(coap_pkt->token, COAP_TOKEN_LEN, current_option, coap_pkt->token_len); - PRINTF("Token (len %u) [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", - coap_pkt->token_len, coap_pkt->token[0], coap_pkt->token[1], - coap_pkt->token[2], coap_pkt->token[3], coap_pkt->token[4], - coap_pkt->token[5], coap_pkt->token[6], coap_pkt->token[7] - ); /*FIXME always prints 8 bytes */ - - /* parse options */ - memset(coap_pkt->options, 0, sizeof(coap_pkt->options)); - current_option += coap_pkt->token_len; - - unsigned int option_number = 0; - unsigned int option_delta = 0; - size_t option_length = 0; - - while(current_option < data + data_len) { - /* payload marker 0xFF, currently only checking for 0xF* because rest is reserved */ - if((current_option[0] & 0xF0) == 0xF0) { - coap_pkt->payload = ++current_option; - coap_pkt->payload_len = data_len - (coap_pkt->payload - data); - - /* also for receiving, the Erbium upper bound is REST_MAX_CHUNK_SIZE */ - if(coap_pkt->payload_len > REST_MAX_CHUNK_SIZE) { - coap_pkt->payload_len = REST_MAX_CHUNK_SIZE; - /* null-terminate payload */ - } - coap_pkt->payload[coap_pkt->payload_len] = '\0'; - - break; - } - - option_delta = current_option[0] >> 4; - option_length = current_option[0] & 0x0F; - ++current_option; - - /* avoids code duplication without function overhead */ - unsigned int *x = &option_delta; - - do { - if(*x == 13) { - *x += current_option[0]; - ++current_option; - } else if(*x == 14) { - *x += 255; - *x += current_option[0] << 8; - ++current_option; - *x += current_option[0]; - ++current_option; - } - }while(x != (unsigned int*)&option_length && (x = (unsigned int*)&option_length)); - - option_number += option_delta; - - PRINTF("OPTION %u (delta %u, len %u): ", option_number, option_delta, - option_length); - - SET_OPTION(coap_pkt, option_number); - - switch(option_number) { - case COAP_OPTION_CONTENT_FORMAT: - coap_pkt->content_format = coap_parse_int_option(current_option, - option_length); - PRINTF("Content-Format [%u]\n", coap_pkt->content_format); - break; - case COAP_OPTION_MAX_AGE: - coap_pkt->max_age = coap_parse_int_option(current_option, - option_length); - PRINTF("Max-Age [%lu]\n", coap_pkt->max_age); - break; - case COAP_OPTION_ETAG: - coap_pkt->etag_len = MIN(COAP_ETAG_LEN, option_length); - bh_memcpy_s(coap_pkt->etag, COAP_ETAG_LEN, current_option, coap_pkt->etag_len); - PRINTF("ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", - coap_pkt->etag_len, coap_pkt->etag[0], coap_pkt->etag[1], - coap_pkt->etag[2], coap_pkt->etag[3], coap_pkt->etag[4], - coap_pkt->etag[5], coap_pkt->etag[6], coap_pkt->etag[7] - ); /*FIXME always prints 8 bytes */ - break; - case COAP_OPTION_ACCEPT: - coap_pkt->accept = coap_parse_int_option(current_option, option_length); - PRINTF("Accept [%u]\n", coap_pkt->accept); - break; - case COAP_OPTION_IF_MATCH: - /* TODO support multiple ETags */ - coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, option_length); - bh_memcpy_s(coap_pkt->if_match, COAP_ETAG_LEN, current_option, coap_pkt->if_match_len); - PRINTF("If-Match %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", - coap_pkt->if_match_len, coap_pkt->if_match[0], - coap_pkt->if_match[1], coap_pkt->if_match[2], - coap_pkt->if_match[3], coap_pkt->if_match[4], - coap_pkt->if_match[5], coap_pkt->if_match[6], - coap_pkt->if_match[7] - ); /* FIXME always prints 8 bytes */ - break; - case COAP_OPTION_IF_NONE_MATCH: - coap_pkt->if_none_match = 1; - PRINTF("If-None-Match\n"); - break; - - case COAP_OPTION_PROXY_URI: -#if COAP_PROXY_OPTION_PROCESSING - coap_pkt->proxy_uri = (char *)current_option; - coap_pkt->proxy_uri_len = option_length; -#endif - PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", coap_pkt->proxy_uri_len, - coap_pkt->proxy_uri); - coap_error_message = "This is a constrained server (Contiki)"; - return PROXYING_NOT_SUPPORTED_5_05; - break; - case COAP_OPTION_PROXY_SCHEME: -#if COAP_PROXY_OPTION_PROCESSING - coap_pkt->proxy_scheme = (char *)current_option; - coap_pkt->proxy_scheme_len = option_length; -#endif - PRINTF("Proxy-Scheme NOT IMPLEMENTED [%.*s]\n", - coap_pkt->proxy_scheme_len, coap_pkt->proxy_scheme); - coap_error_message = "This is a constrained server (Contiki)"; - return PROXYING_NOT_SUPPORTED_5_05; - break; - - case COAP_OPTION_URI_HOST: - coap_pkt->uri_host = (char *)current_option; - coap_pkt->uri_host_len = option_length; - PRINTF("Uri-Host [%.*s]\n", coap_pkt->uri_host_len, coap_pkt->uri_host); - break; - case COAP_OPTION_URI_PORT: - coap_pkt->uri_port = coap_parse_int_option(current_option, - option_length); - PRINTF("Uri-Port [%u]\n", coap_pkt->uri_port); - break; - case COAP_OPTION_URI_PATH: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ - coap_merge_multi_option((char **)&(coap_pkt->uri_path), - &(coap_pkt->uri_path_len), current_option, - option_length, '/'); - PRINTF("Uri-Path [%.*s]\n", coap_pkt->uri_path_len, coap_pkt->uri_path); - break; - case COAP_OPTION_URI_QUERY: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ - coap_merge_multi_option((char **)&(coap_pkt->uri_query), - &(coap_pkt->uri_query_len), current_option, - option_length, '&'); - PRINTF("Uri-Query [%.*s]\n", coap_pkt->uri_query_len, - coap_pkt->uri_query); - break; - - case COAP_OPTION_LOCATION_PATH: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ - coap_merge_multi_option((char **)&(coap_pkt->location_path), - &(coap_pkt->location_path_len), current_option, - option_length, '/'); - PRINTF("Location-Path [%.*s]\n", coap_pkt->location_path_len, - coap_pkt->location_path); - break; - case COAP_OPTION_LOCATION_QUERY: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ - coap_merge_multi_option((char **)&(coap_pkt->location_query), - &(coap_pkt->location_query_len), current_option, - option_length, '&'); - PRINTF("Location-Query [%.*s]\n", coap_pkt->location_query_len, - coap_pkt->location_query); - break; - - case COAP_OPTION_OBSERVE: - coap_pkt->observe = coap_parse_int_option(current_option, - option_length); - PRINTF("Observe [%lu]\n", coap_pkt->observe); - break; - case COAP_OPTION_BLOCK2: - coap_pkt->block2_num = coap_parse_int_option(current_option, - option_length); - coap_pkt->block2_more = (coap_pkt->block2_num & 0x08) >> 3; - coap_pkt->block2_size = 16 << (coap_pkt->block2_num & 0x07); - coap_pkt->block2_offset = (coap_pkt->block2_num & ~0x0000000F) - << (coap_pkt->block2_num & 0x07); - coap_pkt->block2_num >>= 4; - PRINTF("Block2 [%lu%s (%u B/blk)]\n", coap_pkt->block2_num, - coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size); - break; - case COAP_OPTION_BLOCK1: - coap_pkt->block1_num = coap_parse_int_option(current_option, - option_length); - coap_pkt->block1_more = (coap_pkt->block1_num & 0x08) >> 3; - coap_pkt->block1_size = 16 << (coap_pkt->block1_num & 0x07); - coap_pkt->block1_offset = (coap_pkt->block1_num & ~0x0000000F) - << (coap_pkt->block1_num & 0x07); - coap_pkt->block1_num >>= 4; - PRINTF("Block1 [%lu%s (%u B/blk)]\n", coap_pkt->block1_num, - coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size); - break; - case COAP_OPTION_SIZE2: - coap_pkt->size2 = coap_parse_int_option(current_option, option_length); - PRINTF("Size2 [%lu]\n", coap_pkt->size2); - break; - case COAP_OPTION_SIZE1: - coap_pkt->size1 = coap_parse_int_option(current_option, option_length); - PRINTF("Size1 [%lu]\n", coap_pkt->size1); - break; - default: - PRINTF("unknown (%u)\n", option_number); - /* check if critical (odd) */ - if(option_number & 1) { - coap_error_message = "Unsupported critical option"; - return BAD_OPTION_4_02; - } - } - - current_option += option_length; - } /* for */ - PRINTF("-Done parsing-------\n"); - - return NO_ERROR; -} -/*---------------------------------------------------------------------------*/ -/*- REST Engine API ---------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -int -coap_get_query_variable(void *packet, const char *name, const char **output) -{ - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY)) { - return coap_get_variable(coap_pkt->uri_query, coap_pkt->uri_query_len, - name, output); - } - return 0; -} -int -coap_get_post_variable(void *packet, const char *name, const char **output) -{ - coap_packet_t *const coap_pkt = (coap_packet_t *)packet; - - if(coap_pkt->payload_len) { - return coap_get_variable((const char *)coap_pkt->payload, - coap_pkt->payload_len, name, output); - } - return 0; -} -#endif -/*---------------------------------------------------------------------------*/ -int coap_set_status_code(void *packet, unsigned int code) -{ - if (code <= 0xFF) { - ((coap_packet_t *) packet)->code = (uint8_t) code; - return 1; - } else { - return 0; - } -} -/*---------------------------------------------------------------------------*/ -int coap_set_token(void *packet, const uint8_t *token, size_t token_len) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len); - bh_memcpy_s(coap_pkt->token, COAP_TOKEN_LEN, token, coap_pkt->token_len); - - return coap_pkt->token_len; -} -/*---------------------------------------------------------------------------*/ -/*- CoAP REST Implementation API --------------------------------------------*/ -/*---------------------------------------------------------------------------*/ -int coap_get_header_content_format(void *packet, unsigned int *format) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_CONTENT_FORMAT)) { - return 0; - } - *format = coap_pkt->content_format; - return 1; -} -int coap_set_header_content_format(void *packet, unsigned int format) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - coap_pkt->content_format = (coap_content_format_t) format; - SET_OPTION(coap_pkt, COAP_OPTION_CONTENT_FORMAT); - return 1; -} -/*---------------------------------------------------------------------------*/ -int coap_get_header_accept(void *packet, unsigned int *accept) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_ACCEPT)) { - return 0; - } - *accept = coap_pkt->accept; - return 1; -} -int coap_set_header_accept(void *packet, unsigned int accept) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - coap_pkt->accept = (coap_content_format_t) accept; - SET_OPTION(coap_pkt, COAP_OPTION_ACCEPT); - return 1; -} -/*---------------------------------------------------------------------------*/ -int coap_get_header_max_age(void *packet, uint32_t *age) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_MAX_AGE)) { - *age = COAP_DEFAULT_MAX_AGE; - } else { - *age = coap_pkt->max_age; - } - return 1; -} -int coap_set_header_max_age(void *packet, uint32_t age) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - coap_pkt->max_age = age; - SET_OPTION(coap_pkt, COAP_OPTION_MAX_AGE); - return 1; -} -/*---------------------------------------------------------------------------*/ -int coap_get_header_etag(void *packet, const uint8_t **etag) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_ETAG)) { - return 0; - } - *etag = coap_pkt->etag; - return coap_pkt->etag_len; -} -int coap_set_header_etag(void *packet, const uint8_t *etag, size_t etag_len) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - coap_pkt->etag_len = MIN(COAP_ETAG_LEN, etag_len); - bh_memcpy_s(coap_pkt->etag, COAP_ETAG_LEN, etag, coap_pkt->etag_len); - - SET_OPTION(coap_pkt, COAP_OPTION_ETAG); - return coap_pkt->etag_len; -} -/*---------------------------------------------------------------------------*/ -/*FIXME support multiple ETags */ -int coap_get_header_if_match(void *packet, const uint8_t **etag) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_IF_MATCH)) { - return 0; - } - *etag = coap_pkt->if_match; - return coap_pkt->if_match_len; -} -int coap_set_header_if_match(void *packet, const uint8_t *etag, size_t etag_len) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, etag_len); - bh_memcpy_s(coap_pkt->if_match, COAP_ETAG_LEN, etag, - coap_pkt->if_match_len); - - SET_OPTION(coap_pkt, COAP_OPTION_IF_MATCH); - return coap_pkt->if_match_len; -} -/*---------------------------------------------------------------------------*/ -int coap_get_header_if_none_match(void *packet) -{ - return IS_OPTION((coap_packet_t *)packet, - COAP_OPTION_IF_NONE_MATCH) ? 1 : 0; -} -int coap_set_header_if_none_match(void *packet) -{ - SET_OPTION((coap_packet_t * )packet, COAP_OPTION_IF_NONE_MATCH); - return 1; -} -/*---------------------------------------------------------------------------*/ -int coap_get_header_proxy_uri(void *packet, const char **uri) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_PROXY_URI)) { - return 0; - } - *uri = coap_pkt->proxy_uri; - return coap_pkt->proxy_uri_len; -} -int coap_set_header_proxy_uri(void *packet, const char *uri) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - /*TODO Provide alternative that sets Proxy-Scheme and Uri-* options and provide er-coap-conf define */ - - coap_pkt->proxy_uri = uri; - coap_pkt->proxy_uri_len = strlen(uri); - - SET_OPTION(coap_pkt, COAP_OPTION_PROXY_URI); - return coap_pkt->proxy_uri_len; -} -/*---------------------------------------------------------------------------*/ -int coap_get_header_uri_host(void *packet, const char **host) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_URI_HOST)) { - return 0; - } - *host = coap_pkt->uri_host; - return coap_pkt->uri_host_len; -} -int coap_set_header_uri_host(void *packet, const char *host) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - coap_pkt->uri_host = host; - coap_pkt->uri_host_len = strlen(host); - - SET_OPTION(coap_pkt, COAP_OPTION_URI_HOST); - return coap_pkt->uri_host_len; -} -/*---------------------------------------------------------------------------*/ -int coap_get_header_uri_path(void *packet, const char **path) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_URI_PATH)) { - return 0; - } - *path = coap_pkt->uri_path; - return coap_pkt->uri_path_len; -} -int coap_set_header_uri_path(void *packet, const char *path) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - -// while(path[0] == '/') -// ++path; - - coap_pkt->uri_path = path; - coap_pkt->uri_path_len = strlen(path); - - SET_OPTION(coap_pkt, COAP_OPTION_URI_PATH); - return coap_pkt->uri_path_len; -} -/*---------------------------------------------------------------------------*/ -int coap_get_header_uri_query(void *packet, const char **query) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY)) { - return 0; - } - *query = coap_pkt->uri_query; - return coap_pkt->uri_query_len; -} -int coap_set_header_uri_query(void *packet, const char *query) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - while (query[0] == '?') - ++query; - - coap_pkt->uri_query = query; - coap_pkt->uri_query_len = strlen(query); - - SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY); - return coap_pkt->uri_query_len; -} -/*---------------------------------------------------------------------------*/ -int coap_get_header_location_path(void *packet, const char **path) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH)) { - return 0; - } - *path = coap_pkt->location_path; - return coap_pkt->location_path_len; -} -int coap_set_header_location_path(void *packet, const char *path) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - char *query; - - while (path[0] == '/') - ++path; - - if ((query = strchr(path, '?'))) { - coap_set_header_location_query(packet, query + 1); - coap_pkt->location_path_len = query - path; - } else { - coap_pkt->location_path_len = strlen(path); - } - coap_pkt->location_path = path; - - if (coap_pkt->location_path_len > 0) { - SET_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH); - } - return coap_pkt->location_path_len; -} -/*---------------------------------------------------------------------------*/ -int coap_get_header_location_query(void *packet, const char **query) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY)) { - return 0; - } - *query = coap_pkt->location_query; - return coap_pkt->location_query_len; -} -int coap_set_header_location_query(void *packet, const char *query) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - while (query[0] == '?') - ++query; - - coap_pkt->location_query = query; - coap_pkt->location_query_len = strlen(query); - - SET_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY); - return coap_pkt->location_query_len; -} -/*---------------------------------------------------------------------------*/ -int coap_get_header_observe(void *packet, uint32_t *observe) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_OBSERVE)) { - return 0; - } - *observe = coap_pkt->observe; - return 1; -} -int coap_set_header_observe(void *packet, uint32_t observe) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - coap_pkt->observe = observe; - SET_OPTION(coap_pkt, COAP_OPTION_OBSERVE); - return 1; -} -/*---------------------------------------------------------------------------*/ -int coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more, - uint32_t *size, uint32_t *offset) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK2)) { - return 0; - } - /* pointers may be NULL to get only specific block parameters */ - if (num != NULL) { - *num = coap_pkt->block2_num; - } - if (more != NULL) { - *more = coap_pkt->block2_more; - } - if (size != NULL) { - *size = coap_pkt->block2_size; - } - if (offset != NULL) { - *offset = coap_pkt->block2_offset; - } - return 1; -} -int coap_set_header_block2(void *packet, uint32_t num, uint8_t more, - uint32_t size) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (size < 16) { - return 0; - } - if (size > 2048) { - return 0; - } - if (num > 0x0FFFFF) { - return 0; - } - coap_pkt->block2_num = num; - coap_pkt->block2_more = more ? 1 : 0; - coap_pkt->block2_size = size; - - SET_OPTION(coap_pkt, COAP_OPTION_BLOCK2); - return 1; -} -/*---------------------------------------------------------------------------*/ -int coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more, - uint16_t *size, uint32_t *offset) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK1)) { - return 0; - } - /* pointers may be NULL to get only specific block parameters */ - if (num != NULL) { - *num = coap_pkt->block1_num; - } - if (more != NULL) { - *more = coap_pkt->block1_more; - } - if (size != NULL) { - *size = coap_pkt->block1_size; - } - if (offset != NULL) { - *offset = coap_pkt->block1_offset; - } - return 1; -} -int coap_set_header_block1(void *packet, uint32_t num, uint8_t more, - uint16_t size) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (size < 16) { - return 0; - } - if (size > 2048) { - return 0; - } - if (num > 0x0FFFFF) { - return 0; - } - coap_pkt->block1_num = num; - coap_pkt->block1_more = more; - coap_pkt->block1_size = size; - - SET_OPTION(coap_pkt, COAP_OPTION_BLOCK1); - return 1; -} -/*---------------------------------------------------------------------------*/ -int coap_get_header_size2(void *packet, uint32_t *size) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_SIZE2)) { - return 0; - } - *size = coap_pkt->size2; - return 1; -} -int coap_set_header_size2(void *packet, uint32_t size) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - coap_pkt->size2 = size; - SET_OPTION(coap_pkt, COAP_OPTION_SIZE2); - return 1; -} -/*---------------------------------------------------------------------------*/ -int coap_get_header_size1(void *packet, uint32_t *size) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (!IS_OPTION(coap_pkt, COAP_OPTION_SIZE1)) { - return 0; - } - *size = coap_pkt->size1; - return 1; -} -int coap_set_header_size1(void *packet, uint32_t size) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - coap_pkt->size1 = size; - SET_OPTION(coap_pkt, COAP_OPTION_SIZE1); - return 1; -} -/*---------------------------------------------------------------------------*/ -int coap_get_payload(void *packet, const uint8_t **payload) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - if (coap_pkt->payload) { - *payload = coap_pkt->payload; - return coap_pkt->payload_len; - } else { - *payload = NULL; - return 0; - } -} -int coap_set_payload(void *packet, const void *payload, size_t length) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - coap_pkt->payload = (uint8_t *) payload; - coap_pkt->payload_len = MIN(REST_MAX_CHUNK_SIZE, length); - - return coap_pkt->payload_len; -} -/*---------------------------------------------------------------------------*/ diff --git a/core/shared-lib/coap/er-coap/er-coap.h b/core/shared-lib/coap/er-coap/er-coap.h deleted file mode 100755 index 7c15465d2..000000000 --- a/core/shared-lib/coap/er-coap/er-coap.h +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -/** - * \file - * An implementation of the Constrained Application Protocol (RFC). - * \author - * Matthias Kovatsch - */ - -#ifndef ER_COAP_H_ -#define ER_COAP_H_ - -#include "../extension/coap_platforms.h" -#include /* for size_t */ -#include -//#include "contiki-net.h" -#include "er-coap-constants.h" -#include "er-coap-conf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* sanity check for configured values */ -#define COAP_MAX_PACKET_SIZE (COAP_MAX_HEADER_SIZE + REST_MAX_CHUNK_SIZE) -/*#if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_IPH_LEN - UIP_UDPH_LEN) - #error "UIP_CONF_BUFFER_SIZE too small for REST_MAX_CHUNK_SIZE" - #endif - */ - -/* ------------------------------------------------------ */ -/* ------ section added by the coap request --------- */ -/* ------------------------------------------------------ */ - -//typedef int (*restful_response_handler)(void *response,void *data); -#define RX_TIMEOUT (-1) -typedef int (*Tx_Data)(void * coap_ctx, const uip_ipaddr_t *dst_addr, void *buf, int len); -typedef int (*Rx_Data) (void * coap_ctx, void *buf, int len, int timeout); -typedef int (*Request_Handler) (void * coap_ctx, void *); - -typedef int (*CoAP_Res_Handler) (void * request, void * response, char **out_payload, int * payload_len); - -typedef struct _coap_resource_handler -{ - struct _coap_resource_handler * next; - char * url; - CoAP_Res_Handler get_handler; - CoAP_Res_Handler put_handler; - CoAP_Res_Handler post_handler; - CoAP_Res_Handler other_handler; // create | delete -}coap_resource_handler_t; - - - -typedef struct res_block_state -{ - struct res_block_state * next; - char * url; - void * buffer; - int buffer_size; - uint32_t block_num; - uint16_t block_size; - uint16_t content_fmt; - uint32_t last_access; - uint8_t is_get; -} res_block_state_t; - - -typedef struct peer_block_state -{ - struct peer_block_state * next; - struct net_addr_coap peer_addr; - res_block_state_t * list; -}peer_block_state_t; - - -typedef struct coap_context { - uint8_t * buf; - uint32_t buf_len; // the data length - uint32_t buf_size; // the malloced buffer size - - struct net_addr_coap my_addr; - - // the address associated with current buffer - struct net_addr_coap src_addr; - - uint8_t status; - uint8_t is_used; - uint8_t response_on_not_found; - uint16_t default_retrans_cnt; - uint32_t default_retrans_ms; - - Tx_Data tx_data; - Rx_Data rx_data; - - int socket; - char * user_data; - - peer_block_state_t * blockwise_list; - coap_resource_handler_t * resource_handlers; - - void * transactions; - void * transaction_lock; - uint32_t last_checktime; - - void * request_handler; - -#ifdef WITH_DTLS -struct dtls_context_t *dtls_context; -dtls_handler_t dtls_handler; -struct process *process; -#endif /* WITH_DTLS */ - -} coap_context_t; - -int add_resource_handler(coap_context_t * coap_ctx, coap_resource_handler_t * handler); - - -// coap_context_t * coap_context_new(uip_ipaddr_t *my_addr, uint16_t my_port); //CANNOTBUILD -void coap_context_close(coap_context_t *coap_ctx); -void coap_ctx_send(coap_context_t *coap_ctx, uint8_t *data, - uint16_t length); - -/* ---------------- end of section ------------------ */ - - -/* use Erbium CoAP for the REST Engine. Must come before include of rest-engine.h. */ -//#define REST coap_rest_implementation -//#include "rest-engine.h" - -/* REST_MAX_CHUNK_SIZE can be different from 2^x so we need to get next lower 2^x for COAP_MAX_BLOCK_SIZE */ -#ifndef COAP_MAX_BLOCK_SIZE -#define COAP_MAX_BLOCK_SIZE (REST_MAX_CHUNK_SIZE < 32 ? 16 : \ - (REST_MAX_CHUNK_SIZE < 64 ? 32 : \ - (REST_MAX_CHUNK_SIZE < 128 ? 64 : \ - (REST_MAX_CHUNK_SIZE < 256 ? 128 : \ - (REST_MAX_CHUNK_SIZE < 512 ? 256 : \ - (REST_MAX_CHUNK_SIZE < 1024 ? 512 : \ - (REST_MAX_CHUNK_SIZE < 2048 ? 1024 : 2048))))))) -#endif /* COAP_MAX_BLOCK_SIZE */ - -/* direct access into the buffer */ -#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) -#ifdef NETSTACK_CONF_WITH_IPV6 -#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) -#else -#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN]) -#endif - -/* bitmap for set options */ -enum { OPTION_MAP_SIZE = sizeof(uint8_t) * 8 }; - -#define SET_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] |= 1 << (opt % OPTION_MAP_SIZE)) -#define IS_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] & (1 << (opt % OPTION_MAP_SIZE))) - -/* parsed message struct */ -typedef struct { - uint8_t *buffer; /* pointer to CoAP header / incoming packet buffer / memory to serialize packet */ - - uint8_t version; - coap_message_type_t type; - uint8_t code; - uint16_t mid; - - uint8_t token_len; - uint8_t token[COAP_TOKEN_LEN]; - - uint8_t options[COAP_OPTION_SIZE1 / OPTION_MAP_SIZE + 1]; /* bitmap to check if option is set */ - - coap_content_format_t content_format; /* parse options once and store; allows setting options in random order */ - uint32_t max_age; - uint8_t etag_len; - uint8_t etag[COAP_ETAG_LEN]; - size_t proxy_uri_len; - const char *proxy_uri; - size_t proxy_scheme_len; - const char *proxy_scheme; - size_t uri_host_len; - const char *uri_host; - size_t location_path_len; - const char *location_path; - uint16_t uri_port; - size_t location_query_len; - const char *location_query; - size_t uri_path_len; - const char *uri_path; - int32_t observe; - coap_content_format_t accept; - uint8_t if_match_len; - uint8_t if_match[COAP_ETAG_LEN]; - uint32_t block2_num; - uint8_t block2_more; - uint32_t block2_size; - uint32_t block2_offset; - uint32_t block1_num; - uint8_t block1_more; - uint32_t block1_size; - uint32_t block1_offset; - uint32_t size2; - uint32_t size1; - size_t uri_query_len; - const char *uri_query; - uint8_t if_none_match; - - uint32_t payload_len; - uint8_t *payload; -} coap_packet_t; - -/* option format serialization */ -#define COAP_SERIALIZE_INT_OPTION(number, field, text) \ - if(IS_OPTION(coap_pkt, number)) { \ - PRINTF(text " [%u]\n", coap_pkt->field); \ - option += coap_serialize_int_option(number, current_number, option, coap_pkt->field); \ - current_number = number; \ - } -#define COAP_SERIALIZE_BYTE_OPTION(number, field, text) \ - if(IS_OPTION(coap_pkt, number)) { \ - PRINTF(text " %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", coap_pkt->field##_len, \ - coap_pkt->field[0], \ - coap_pkt->field[1], \ - coap_pkt->field[2], \ - coap_pkt->field[3], \ - coap_pkt->field[4], \ - coap_pkt->field[5], \ - coap_pkt->field[6], \ - coap_pkt->field[7] \ - ); /* FIXME always prints 8 bytes */ \ - option += coap_serialize_array_option(number, current_number, option, coap_pkt->field, coap_pkt->field##_len, '\0'); \ - current_number = number; \ - } -#define COAP_SERIALIZE_STRING_OPTION(number, field, splitter, text) \ - if(IS_OPTION(coap_pkt, number)) { \ - PRINTF(text " [%.*s]\n", coap_pkt->field##_len, coap_pkt->field); \ - option += coap_serialize_array_option(number, current_number, option, (uint8_t *)coap_pkt->field, coap_pkt->field##_len, splitter); \ - current_number = number; \ - } -#define COAP_SERIALIZE_BLOCK_OPTION(number, field, text) \ - if(IS_OPTION(coap_pkt, number)) \ - { \ - PRINTF(text " [%lu%s (%u B/blk)]\n", coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \ - uint32_t block = coap_pkt->field##_num << 4; \ - if(coap_pkt->field##_more) { block |= 0x8; } \ - block |= 0xF & coap_log_2(coap_pkt->field##_size / 16); \ - PRINTF(text " encoded: 0x%lX\n", block); \ - option += coap_serialize_int_option(number, current_number, option, block); \ - current_number = number; \ - } - -/* to store error code and human-readable payload */ -extern coap_status_t erbium_status_code; -extern char *coap_error_message; - -void coap_init_connection(uint16_t port); -uint16_t coap_get_mid(void); - -void coap_init_message(void *packet, coap_message_type_t type, uint8_t code, - uint16_t mid); -size_t coap_serialize_message(void *packet, uint8_t *buffer); -void coap_send_message(coap_context_t*, uip_ipaddr_t *addr, uint16_t port, uint8_t *data, - uint16_t length); -coap_status_t coap_parse_message(void *request, uint8_t *data, - uint16_t data_len); - -int coap_get_query_variable(void *packet, const char *name, - const char **output); -int coap_get_post_variable(void *packet, const char *name, - const char **output); - -/*---------------------------------------------------------------------------*/ - -int coap_set_status_code(void *packet, unsigned int code); - -int coap_set_token(void *packet, const uint8_t *token, size_t token_len); - -int coap_get_header_content_format(void *packet, unsigned int *format); -int coap_set_header_content_format(void *packet, unsigned int format); - -int coap_get_header_accept(void *packet, unsigned int *accept); -int coap_set_header_accept(void *packet, unsigned int accept); - -int coap_get_header_max_age(void *packet, uint32_t *age); -int coap_set_header_max_age(void *packet, uint32_t age); - -int coap_get_header_etag(void *packet, const uint8_t **etag); -int coap_set_header_etag(void *packet, const uint8_t *etag, size_t etag_len); - -int coap_get_header_if_match(void *packet, const uint8_t **etag); -int coap_set_header_if_match(void *packet, const uint8_t *etag, - size_t etag_len); - -int coap_get_header_if_none_match(void *packet); -int coap_set_header_if_none_match(void *packet); - -int coap_get_header_proxy_uri(void *packet, const char **uri); /* in-place string might not be 0-terminated. */ -int coap_set_header_proxy_uri(void *packet, const char *uri); - -int coap_get_header_proxy_scheme(void *packet, const char **scheme); /* in-place string might not be 0-terminated. */ -int coap_set_header_proxy_scheme(void *packet, const char *scheme); - -int coap_get_header_uri_host(void *packet, const char **host); /* in-place string might not be 0-terminated. */ -int coap_set_header_uri_host(void *packet, const char *host); - -int coap_get_header_uri_path(void *packet, const char **path); /* in-place string might not be 0-terminated. */ -int coap_set_header_uri_path(void *packet, const char *path); - -int coap_get_header_uri_query(void *packet, const char **query); /* in-place string might not be 0-terminated. */ -int coap_set_header_uri_query(void *packet, const char *query); - -int coap_get_header_location_path(void *packet, const char **path); /* in-place string might not be 0-terminated. */ -int coap_set_header_location_path(void *packet, const char *path); /* also splits optional query into Location-Query option. */ - -int coap_get_header_location_query(void *packet, const char **query); /* in-place string might not be 0-terminated. */ -int coap_set_header_location_query(void *packet, const char *query); - -int coap_get_header_observe(void *packet, uint32_t *observe); -int coap_set_header_observe(void *packet, uint32_t observe); - -int coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more, - uint32_t *size, uint32_t *offset); -int coap_set_header_block2(void *packet, uint32_t num, uint8_t more, - uint32_t size); - -int coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more, - uint16_t *size, uint32_t *offset); -int coap_set_header_block1(void *packet, uint32_t num, uint8_t more, - uint16_t size); - -int coap_get_header_size2(void *packet, uint32_t *size); -int coap_set_header_size2(void *packet, uint32_t size); - -int coap_get_header_size1(void *packet, uint32_t *size); -int coap_set_header_size1(void *packet, uint32_t size); - -int coap_get_payload(void *packet, const uint8_t **payload); -int coap_set_payload(void *packet, const void *payload, size_t length); - -#ifdef __cplusplus -} -#endif - -#endif /* ER_COAP_H_ */ diff --git a/core/shared-lib/coap/extension/Makefile b/core/shared-lib/coap/extension/Makefile deleted file mode 100644 index 32d65d0be..000000000 --- a/core/shared-lib/coap/extension/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -obj-y += coap_over_tcp.o diff --git a/core/shared-lib/coap/extension/coap_conversion.c b/core/shared-lib/coap/extension/coap_conversion.c deleted file mode 100644 index 6251499db..000000000 --- a/core/shared-lib/coap/extension/coap_conversion.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "coap_ext.h" - -char * coap_get_full_url_alloc(coap_packet_t * request) -{ - const char *url = NULL; - const char * query = NULL; - int url_len = coap_get_header_uri_path(request, &url); - int query_len = coap_get_header_uri_query(request, &query); - - if (url_len == 0) - return NULL; - - char * url_alloc = (char*) bh_malloc(url_len + 1 + query_len + 1); - memcpy(url_alloc, url, url_len); - url_alloc[url_len] = 0; - - // make the url looks like /abc?e=f - if (query_len != 0) { - strcat(url_alloc, "&"); - memcpy(url_alloc + strlen(url_alloc), query, query_len); - url_alloc[url_len + 1 + query_len] = 0; - } - - return url_alloc; -} - -void convert_request_to_coap_packet(request_t * req, coap_packet_t * packet) -{ - coap_init_message(packet, COAP_TYPE_NON, req->action, req->mid); - coap_set_token(packet, (uint8_t *) &req->mid, sizeof(req->mid)); - coap_set_header_content_format(packet, req->fmt); - - coap_set_header_uri_path(packet, req->url); - - coap_set_payload(packet, req->payload, req->payload_len); - - packet->mid = req->mid; -} - -void convert_response_to_coap_packet(response_t * response, - coap_packet_t * packet) -{ - coap_init_message(packet, COAP_TYPE_NON, response->status, response->mid); - coap_set_token(packet, (uint8_t *) &response->mid, sizeof(response->mid)); - coap_set_header_content_format(packet, response->fmt); - coap_set_payload(packet, response->payload, response->payload_len); - - packet->mid = response->mid; -} - -// return: the length of url. -// note: the url is probably not end with 0 due to coap packing design. -int convert_coap_packet_to_request(coap_packet_t *packet, request_t *request) -{ - const char *url = NULL; - int url_len = coap_get_header_uri_path(packet, &url); - - memset(request, 0, sizeof(*request)); - - request->action = packet->code; - request->fmt = packet->content_format; - if (packet->token_len == 4) { - request->mid = *((unsigned long *) packet->token); - } else { - request->mid = packet->mid; - } - request->payload = packet->payload; - request->payload_len = packet->payload_len; - request->url = (char *)url; - return url_len; -} - -void convert_coap_packet_to_response(coap_packet_t *packet, - response_t *response) -{ - memset(response, 0, sizeof(*response)); - - response->status = packet->code; - response->fmt = packet->content_format; - if (packet->token_len == 4) { - response->mid = *((unsigned long *) packet->token); - } else { - response->mid = packet->mid; - } - - response->payload = packet->payload; - response->payload_len = packet->payload_len; - return; -} diff --git a/core/shared-lib/coap/extension/coap_ext.h b/core/shared-lib/coap/extension/coap_ext.h old mode 100755 new mode 100644 index 416393f15..f61deac27 --- a/core/shared-lib/coap/extension/coap_ext.h +++ b/core/shared-lib/coap/extension/coap_ext.h @@ -6,8 +6,7 @@ #ifndef COAP_EXTENSION_COAP_EXT_H_ #define COAP_EXTENSION_COAP_EXT_H_ -#include "er-coap.h" -#include "shared_utils.h" +#include "coap-constants.h" #ifdef __cplusplus extern "C" { @@ -15,31 +14,6 @@ extern "C" { #define COAP_EVENT (COAP_DELETE + 2) -char * coap_get_full_url_alloc(coap_packet_t * request); - -coap_status_t coap_parse_message_tcp(void *packet, uint8_t *data, - uint32_t data_len); - -int coap_serialize_message_tcp(void *packet, uint8_t ** buffer_out); -int coap_set_payload_tcp(void *packet, const void *payload, size_t length); -uint8_t coap_is_request(coap_packet_t * coap_message); - -uint16_t coap_find_mid(uint8_t *buffer); -uint8_t coap_find_code(uint8_t *buffer); -void coap_change_mid(uint8_t *buffer, uint16_t id); - -int add_resource_handler(coap_context_t * coap_ctx, - coap_resource_handler_t * handler); -uint32_t check_blockwise_timeout_ms(coap_context_t * coap_ctx, int timeout_sec); - -int convert_coap_packet_to_request(coap_packet_t *packet, request_t *request); -void convert_coap_packet_to_response(coap_packet_t *packet, - response_t *response); - -void convert_response_to_coap_packet(response_t * response, - coap_packet_t * packet); -void convert_request_to_coap_packet(request_t * req, coap_packet_t * packet); - #ifdef __cplusplus } #endif diff --git a/core/shared-lib/coap/extension/coap_over_tcp.c b/core/shared-lib/coap/extension/coap_over_tcp.c deleted file mode 100755 index ee0dbd27a..000000000 --- a/core/shared-lib/coap/extension/coap_over_tcp.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include -#include -#include "bh_common.h" -#include "er-coap.h" -#include "coap_ext.h" -#include "er-coap-constants.h" - -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) -#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) -#else -#define PRINTF(...) -#define PRINT6ADDR(addr) -#define PRINTLLADDR(addr) -#endif - -extern size_t -coap_serialize_array_option(unsigned int number, unsigned int current_number, - uint8_t *buffer, uint8_t *array, size_t length, char split_char); -extern size_t -coap_serialize_int_option(unsigned int number, unsigned int current_number, - uint8_t *buffer, uint32_t value); -extern uint16_t coap_log_2(uint16_t value); -extern uint32_t coap_parse_int_option(uint8_t *bytes, size_t length); -extern void -coap_merge_multi_option(char **dst, size_t *dst_len, uint8_t *option, - size_t option_len, char separator); - -/* - * - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |Len=15 | TKL | Extended Length (32 bits) - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | Code | Token (if any, TKL bytes) ... - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Options (if any) ... - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |1 1 1 1 1 1 1 1| Payload (if any) ... - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - */ - -int coap_set_payload_tcp(void *packet, const void *payload, size_t length) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - coap_pkt->payload = (uint8_t *) payload; - coap_pkt->payload_len = MIN(REST_MAX_CHUNK_SIZE, length); - - return coap_pkt->payload_len; -} - -#if 0 -static size_t coap_calc_ext_len_field(int len) -{ - if(len < 13) - return 0; - else if(len <= (0xFF+13)) - return 1; - else if(len <= (0xFFFF+269)) - return 2; - else if(len < (0xFFFFFFFF+65805)) - return 4; - else - return 0; -} -#endif - -static size_t coap_max_options_offset(void *packet) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - return 6 + coap_pkt->token_len; -} - -int coap_serialize_message_tcp(void *packet, uint8_t ** buffer_out) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - uint8_t buffer[128]; - - uint8_t *option = buffer; - unsigned int current_number = 0; - - if (coap_pkt->uri_path_len > 100) { - *buffer_out = 0; - return -1; - } - - /* Serialize options */ - current_number = 0; - if (0 == coap_pkt->token_len) { - bh_memcpy_s(coap_pkt->token, COAP_TOKEN_LEN, &coap_pkt->mid, - sizeof(coap_pkt->mid)); - coap_pkt->token_len = sizeof(coap_pkt->mid); - }PRINTF("-Serializing options at %p-\n", option); - - /* The options must be serialized in the order of their number */ - COAP_SERIALIZE_BYTE_OPTION(COAP_OPTION_IF_MATCH, if_match, "If-Match"); - COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_HOST, uri_host, '\0', - "Uri-Host"); - COAP_SERIALIZE_BYTE_OPTION(COAP_OPTION_ETAG, etag, "ETag"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_IF_NONE_MATCH, - content_format - coap_pkt-> content_format /* hack to get a zero field */, - "If-None-Match"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_OBSERVE, observe, "Observe"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_URI_PORT, uri_port, "Uri-Port"); - COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_LOCATION_PATH, location_path, '/', - "Location-Path"); - COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_PATH, uri_path, 0, //'/', - "Uri-Path"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_CONTENT_FORMAT, content_format, - "Content-Format"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_MAX_AGE, max_age, "Max-Age"); - COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_QUERY, uri_query, '&', - "Uri-Query"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_ACCEPT, accept, "Accept"); - COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_LOCATION_QUERY, location_query, - '&', "Location-Query"); - COAP_SERIALIZE_BLOCK_OPTION(COAP_OPTION_BLOCK2, block2, "Block2"); - COAP_SERIALIZE_BLOCK_OPTION(COAP_OPTION_BLOCK1, block1, "Block1"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_SIZE2, size2, "Size2"); - COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_PROXY_URI, proxy_uri, '\0', - "Proxy-Uri"); - COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_PROXY_SCHEME, proxy_scheme, '\0', - "Proxy-Scheme"); - COAP_SERIALIZE_INT_OPTION(COAP_OPTION_SIZE1, size1, "Size1"); - - /* Pack payload */ - if (coap_pkt->payload_len) { - *option = 0xFF; - ++option; - } - uint32_t option_len = option - &buffer[0]; - - uint8_t * p = (uint8_t *) os_malloc( - coap_max_options_offset(packet) + option_len - + coap_pkt->payload_len); - if (p == NULL) - return 0; - *buffer_out = p; - - uint8_t first_4bits; - - *p = (coap_pkt->token_len & 0xF); - uint32_t len = option_len + coap_pkt->payload_len; - - if (len < 13) { - first_4bits = len; - *p++ |= first_4bits << 4; - } else if (len <= (0xFF + 13)) { - first_4bits = 13; - *p++ |= first_4bits << 4; - *p++ = len - 13; - } else if (len <= (0xFFFF + 269)) { - first_4bits = 14; - *p++ |= first_4bits << 4; - len -= 269; - *p = (uint8_t)(len >> 8); - p++; - *p = (uint8_t)(len & 0xFF); - p++; - } else { - first_4bits = 15; - *p++ |= first_4bits << 4; - - len -= 65805; - *p++ = (uint8_t)(len >> 24); - *p++ = (uint8_t)(len >> 16); - *p++ = (uint8_t)(len >> 8); - *p++ = (uint8_t)(len & 0xFF); - } - - *p = coap_pkt->code; - p++; - - if (coap_pkt->token_len) - bh_memcpy_s(p, coap_pkt->token_len, coap_pkt->token, - coap_pkt->token_len); - p += coap_pkt->token_len; - - bh_memcpy_s(p, option_len, buffer, option_len); - p += option_len; - - bh_memcpy_s(p, coap_pkt->payload_len, coap_pkt->payload, - coap_pkt->payload_len); - p += coap_pkt->payload_len; - - return (p - *buffer_out); /* packet length */ -} - -coap_status_t coap_parse_message_tcp(void *packet, uint8_t *data, - uint32_t data_len) -{ - coap_packet_t * const coap_pkt = (coap_packet_t *) packet; - - /* initialize packet */ - memset(coap_pkt, 0, sizeof(coap_packet_t)); - - /* pointer to packet bytes */ - coap_pkt->buffer = data; - - /* parse header fields */ - coap_pkt->version = 1; - coap_pkt->type = COAP_TYPE_NON; - coap_pkt->token_len = MIN(COAP_TOKEN_LEN, data[0] & 0xF); - coap_pkt->mid = 0; - - uint8_t *p = data; - uint8_t first_4bits = data[0] >> 4; - - uint32_t options_payload_size; - uint8_t ext_len_field = 0; - if (first_4bits < 13) { - options_payload_size = first_4bits; - p++; - } else if (first_4bits == 13) { - ext_len_field = 1; - options_payload_size = data[1] + 13; - p += 2; - } else if (first_4bits == 14) { - ext_len_field = 2; - options_payload_size = (uint16_t)(data[1] << 8) + data[2] + 269; - p += 3; - } else if (first_4bits == 15) { - ext_len_field = 4; - options_payload_size = (data[1] << 24) + (data[2] << 16) - + (data[3] << 8) + data[4] + 65805; - p += 5; - } - - // check the data size is smaller than the size indicated by the packet - if (ext_len_field + coap_pkt->token_len + 2 + options_payload_size - > data_len) - return BAD_REQUEST_4_00; - - coap_pkt->code = *p++; - if (coap_pkt->token_len) - bh_memcpy_s(coap_pkt->token, COAP_TOKEN_LEN, p, coap_pkt->token_len); - - if (coap_pkt->token_len >= 2) { - union { - uint16_t *mid; - uint8_t *token; - } mid_token_union; - - mid_token_union.token = coap_pkt->token; - coap_pkt->mid = *(mid_token_union.mid); - } - - p += coap_pkt->token_len; - - uint8_t *current_option = p; - uint8_t * option_start = p; - - /* parse options */ - memset(coap_pkt->options, 0, sizeof(coap_pkt->options)); - - unsigned int option_number = 0; - unsigned int option_delta = 0; - size_t option_length = 0; - - while (current_option < data + data_len) { - /* payload marker 0xFF, currently only checking for 0xF* because rest is reserved */ - if ((current_option[0] & 0xF0) == 0xF0) { - coap_pkt->payload = ++current_option; - coap_pkt->payload_len = options_payload_size - - (coap_pkt->payload - option_start); - //coap_pkt->payload_len = data_len - (coap_pkt->payload - data); - break; - } - - option_delta = current_option[0] >> 4; - option_length = current_option[0] & 0x0F; - ++current_option; - - /* avoids code duplication without function overhead */ - unsigned int *x = &option_delta; - - do { - if (*x == 13) { - *x += current_option[0]; - ++current_option; - } else if (*x == 14) { - *x += 255; - *x += current_option[0] << 8; - ++current_option; - *x += current_option[0]; - ++current_option; - } - } while (x != (unsigned int*) &option_length && (x = - (unsigned int*) &option_length)); - option_length = *x; - option_number += option_delta; - - PRINTF("OPTION %u (delta %u, len %u): ", option_number, option_delta, - option_length); - - SET_OPTION(coap_pkt, option_number); - - switch (option_number) { - - case COAP_OPTION_CONTENT_FORMAT: - coap_pkt->content_format = coap_parse_int_option(current_option, - option_length); - PRINTF("Content-Format [%u]\n", coap_pkt->content_format); - break; - case COAP_OPTION_MAX_AGE: - coap_pkt->max_age = coap_parse_int_option(current_option, - option_length); - PRINTF("Max-Age [%lu]\n", coap_pkt->max_age); - break; - case COAP_OPTION_ETAG: - coap_pkt->etag_len = MIN(COAP_ETAG_LEN, option_length); - bh_memcpy_s(coap_pkt->etag, COAP_ETAG_LEN, current_option, - coap_pkt->etag_len); - PRINTF("ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", - coap_pkt->etag_len, coap_pkt->etag[0], coap_pkt->etag[1], - coap_pkt->etag[2], coap_pkt->etag[3], coap_pkt->etag[4], - coap_pkt->etag[5], coap_pkt->etag[6], coap_pkt->etag[7] - ); /*FIXME always prints 8 bytes */ - break; - case COAP_OPTION_ACCEPT: - coap_pkt->accept = coap_parse_int_option(current_option, - option_length); - PRINTF("Accept [%u]\n", coap_pkt->accept); - break; - case COAP_OPTION_IF_MATCH: - /* TODO support multiple ETags */ - coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, option_length); - bh_memcpy_s(coap_pkt->if_match, COAP_ETAG_LEN, current_option, - coap_pkt->if_match_len); - PRINTF("If-Match %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", - coap_pkt->if_match_len, coap_pkt->if_match[0], - coap_pkt->if_match[1], coap_pkt->if_match[2], - coap_pkt->if_match[3], coap_pkt->if_match[4], - coap_pkt->if_match[5], coap_pkt->if_match[6], - coap_pkt->if_match[7] - ); /* FIXME always prints 8 bytes */ - break; - case COAP_OPTION_IF_NONE_MATCH: - coap_pkt->if_none_match = 1; - PRINTF("If-None-Match\n"); - break; - - case COAP_OPTION_PROXY_URI: -#if COAP_PROXY_OPTION_PROCESSING - coap_pkt->proxy_uri = (char *)current_option; - coap_pkt->proxy_uri_len = option_length; -#endif - PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", coap_pkt->proxy_uri_len, - coap_pkt->proxy_uri); - coap_error_message = "This is a constrained server (Contiki)"; - return PROXYING_NOT_SUPPORTED_5_05; - break; - case COAP_OPTION_PROXY_SCHEME: -#if COAP_PROXY_OPTION_PROCESSING - coap_pkt->proxy_scheme = (char *)current_option; - coap_pkt->proxy_scheme_len = option_length; -#endif - PRINTF("Proxy-Scheme NOT IMPLEMENTED [%.*s]\n", - coap_pkt->proxy_scheme_len, coap_pkt->proxy_scheme); - coap_error_message = "This is a constrained server (Contiki)"; - return PROXYING_NOT_SUPPORTED_5_05; - break; - - case COAP_OPTION_URI_HOST: - coap_pkt->uri_host = (char *) current_option; - coap_pkt->uri_host_len = option_length; - PRINTF("Uri-Host [%.*s]\n", coap_pkt->uri_host_len, coap_pkt->uri_host); - break; - case COAP_OPTION_URI_PORT: - coap_pkt->uri_port = coap_parse_int_option(current_option, - option_length); - PRINTF("Uri-Port [%u]\n", coap_pkt->uri_port); - break; - case COAP_OPTION_URI_PATH: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ - coap_merge_multi_option((char **) &(coap_pkt->uri_path), - &(coap_pkt->uri_path_len), current_option, option_length, - '/'); - PRINTF("Uri-Path [%.*s]\n", coap_pkt->uri_path_len, coap_pkt->uri_path); - break; - case COAP_OPTION_URI_QUERY: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ - coap_merge_multi_option((char **) &(coap_pkt->uri_query), - &(coap_pkt->uri_query_len), current_option, option_length, - '&'); - PRINTF("Uri-Query [%.*s]\n", coap_pkt->uri_query_len, - coap_pkt->uri_query); - break; - - case COAP_OPTION_LOCATION_PATH: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ - coap_merge_multi_option((char **) &(coap_pkt->location_path), - &(coap_pkt->location_path_len), current_option, - option_length, '/'); - PRINTF("Location-Path [%.*s]\n", coap_pkt->location_path_len, - coap_pkt->location_path); - break; - case COAP_OPTION_LOCATION_QUERY: - /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ - coap_merge_multi_option((char **) &(coap_pkt->location_query), - &(coap_pkt->location_query_len), current_option, - option_length, '&'); - PRINTF("Location-Query [%.*s]\n", coap_pkt->location_query_len, - coap_pkt->location_query); - break; - - case COAP_OPTION_OBSERVE: - coap_pkt->observe = coap_parse_int_option(current_option, - option_length); - PRINTF("Observe [%lu]\n", coap_pkt->observe); - break; - case COAP_OPTION_BLOCK2: - coap_pkt->block2_num = coap_parse_int_option(current_option, - option_length); - coap_pkt->block2_more = (coap_pkt->block2_num & 0x08) >> 3; - coap_pkt->block2_size = 16 << (coap_pkt->block2_num & 0x07); - coap_pkt->block2_offset = (coap_pkt->block2_num & ~0x0000000F) - << (coap_pkt->block2_num & 0x07); - coap_pkt->block2_num >>= 4; - PRINTF("Block2 [%lu%s (%u B/blk)]\n", coap_pkt->block2_num, - coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size); - break; - case COAP_OPTION_BLOCK1: - coap_pkt->block1_num = coap_parse_int_option(current_option, - option_length); - coap_pkt->block1_more = (coap_pkt->block1_num & 0x08) >> 3; - coap_pkt->block1_size = 16 << (coap_pkt->block1_num & 0x07); - coap_pkt->block1_offset = (coap_pkt->block1_num & ~0x0000000F) - << (coap_pkt->block1_num & 0x07); - coap_pkt->block1_num >>= 4; - PRINTF("Block1 [%lu%s (%u B/blk)]\n", coap_pkt->block1_num, - coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size); - break; - case COAP_OPTION_SIZE2: - coap_pkt->size2 = coap_parse_int_option(current_option, - option_length); - PRINTF("Size2 [%lu]\n", coap_pkt->size2); - break; - case COAP_OPTION_SIZE1: - coap_pkt->size1 = coap_parse_int_option(current_option, - option_length); - PRINTF("Size1 [%lu]\n", coap_pkt->size1); - break; - default: - PRINTF("unknown (%u)\n", option_number); - /* check if critical (odd) */ - if (option_number & 1) { - coap_error_message = "Unsupported critical option"; - return BAD_OPTION_4_02; - } - } - - current_option += option_length; - } /* for */ - PRINTF("-Done parsing-------\n"); - - return NO_ERROR; -} - diff --git a/core/shared-lib/coap/extension/coap_platforms.h b/core/shared-lib/coap/extension/coap_platforms.h deleted file mode 100755 index be5302b07..000000000 --- a/core/shared-lib/coap/extension/coap_platforms.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef COAP_PLATFORMS_H_ -#define COAP_PLATFORMS_H_ -#ifdef __cplusplus -extern "C" { -#endif -#include "bh_platform.h" -#include -#include -#include -/*#include "list_coap.h"*/ -#include - -#define COAP_TRANS_LOCK(ctx) coap_lock(ctx->transaction_lock) -#define COAP_TRANS_UNLOCK(ctx ) coap_unlock(ctx->transaction_lock) - -/* REST_MAX_CHUNK_SIZE is the max size of payload. - * The maximum buffer size that is provided for resource responses and must be respected due to the limited IP buffer. - * Larger data must be handled by the resource and will be sent chunk-wise through a TCP stream or CoAP blocks. - */ -#ifndef REST_MAX_CHUNK_SIZE -#define REST_MAX_CHUNK_SIZE (1024*1024) -#endif - -#ifndef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif /* MIN */ - -#define CLOCK_SECOND 1000 - -typedef enum { - A_Raw, A_Sock_Addr, A_IP_Addr, A_Custom -} Net_Addr_Type; - -#define NET_ADDR_RAW_SIZE 32 - -typedef struct net_addr_coap { - Net_Addr_Type addr_type; - union { - char raw[NET_ADDR_RAW_SIZE]; - struct sockaddr_in sock_addr; - } u; - uint16_t port; - uint16_t addr_len; -} net_addr_t; - -#define uip_ipaddr_t struct net_addr_coap - -#define memb_free(x, y) free(x) - -void set_addr_ip(uip_ipaddr_t *, char * ip, int port); -uip_ipaddr_t * new_net_addr(Net_Addr_Type type); -void copy_net_addr(uip_ipaddr_t * dest, uip_ipaddr_t * src); -bool compare_net_addr(uip_ipaddr_t * dest, uip_ipaddr_t * src); - -uint32_t get_elpased_ms(uint32_t * last_system_clock); -uint32_t get_platform_time(); -uint32_t get_platform_time_sec(); - -void coap_sleep_ms(uint32_t ms); -void coap_lock(void *); -void coap_unlock(void *); -void * coap_create_lock(); -void coap_free_lock(void *); - -void *xalloc(uint32_t size); - -#define os_malloc bh_malloc -#define os_free bh_free - -#ifdef __cplusplus -} -#endif -#endif /* COAP_PLATFORMS_H_ */ diff --git a/core/shared-lib/include/bh_common.h b/core/shared-lib/include/bh_common.h index 8e309ad78..831ffe8a4 100644 --- a/core/shared-lib/include/bh_common.h +++ b/core/shared-lib/include/bh_common.h @@ -8,7 +8,6 @@ #include "bh_assert.h" #include "bh_platform.h" -#include "bh_log.h" #include "bh_list.h" typedef void (*bh_print_function_t)(const char* message); diff --git a/core/shared-lib/include/bh_memory.h b/core/shared-lib/include/bh_memory.h index b2c091d2f..4b3aa86db 100644 --- a/core/shared-lib/include/bh_memory.h +++ b/core/shared-lib/include/bh_memory.h @@ -45,7 +45,7 @@ void bh_memory_destroy(); * Get the pool size of memory, if memory is initialized with allocator, * return 1GB by default. */ -int bh_memory_pool_size(); +unsigned bh_memory_pool_size(); #if BEIHAI_ENABLE_MEMORY_PROFILING == 0 diff --git a/core/shared-lib/include/bh_queue.h b/core/shared-lib/include/bh_queue.h index 56f8b8560..92e9b014e 100644 --- a/core/shared-lib/include/bh_queue.h +++ b/core/shared-lib/include/bh_queue.h @@ -54,7 +54,7 @@ void bh_queue_destroy(bh_queue *queue); char * bh_message_payload(bh_message_t message); -int bh_message_payload_len(bh_message_t message); +uint32 bh_message_payload_len(bh_message_t message); int bh_message_type(bh_message_t message); bh_message_t bh_new_msg(unsigned short tag, void *body, unsigned int len, diff --git a/core/shared-lib/mem-alloc/bh_memory.c b/core/shared-lib/mem-alloc/bh_memory.c index 45c252b12..236bf4faa 100644 --- a/core/shared-lib/mem-alloc/bh_memory.c +++ b/core/shared-lib/mem-alloc/bh_memory.c @@ -95,7 +95,7 @@ void bh_memory_destroy() memory_mode = MEMORY_MODE_UNKNOWN; } -int bh_memory_pool_size() +unsigned bh_memory_pool_size() { if (memory_mode == MEMORY_MODE_POOL) return global_pool_size; @@ -155,7 +155,7 @@ void* bh_malloc_profile(const char *file, profile = bh_malloc_internal(sizeof(memory_profile_t)); if (!profile) { vm_mutex_unlock(&profile_lock); - memcpy(p, &size, sizeof(size)); + bh_memcpy_s(p, size + 8, &size, sizeof(size)); return (char *)p + 8; } @@ -171,7 +171,7 @@ void* bh_malloc_profile(const char *file, vm_mutex_unlock(&profile_lock); - memcpy(p, &size, sizeof(size)); + bh_memcpy_s(p, size + 8, &size, sizeof(size)); memory_in_use += size; memory_profile_print(file, line, func, size); diff --git a/core/shared-lib/mem-alloc/ems/ems_alloc.c b/core/shared-lib/mem-alloc/ems/ems_alloc.c index a9c5c6e74..2724434a7 100644 --- a/core/shared-lib/mem-alloc/ems/ems_alloc.c +++ b/core/shared-lib/mem-alloc/ems/ems_alloc.c @@ -94,7 +94,7 @@ static void unlink_hmu(gc_heap_t *heap, hmu_t *hmu) size = hmu_get_size(hmu); if (HMU_IS_FC_NORMAL(size)) { - int node_idx = size >> 3; + uint32 node_idx = size >> 3; hmu_normal_node_t* node = heap->kfc_normal_list[node_idx].next; hmu_normal_node_t** p = &(heap->kfc_normal_list[node_idx].next); while (node) { @@ -120,7 +120,7 @@ static void hmu_set_free_size(hmu_t *hmu) bh_assert(hmu && hmu_get_ut(hmu) == HMU_FC); size = hmu_get_size(hmu); - *((int*) ((char*) hmu + size) - 1) = size; + *((uint32*) ((char*) hmu + size) - 1) = size; } /* Add free chunk back to KFC*/ @@ -135,7 +135,7 @@ void gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size) { hmu_normal_node_t *np = NULL; hmu_tree_node_t *root = NULL, *tp = NULL, *node = NULL; - int node_idx; + uint32 node_idx; bh_assert(gci_is_heap_valid(heap)); bh_assert( @@ -203,7 +203,7 @@ void gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size) BH_STATIC hmu_t *alloc_hmu(gc_heap_t *heap, gc_size_t size) { hmu_normal_node_t *node = NULL, *p = NULL; - int node_idx = 0, init_node_idx = 0; + uint32 node_idx = 0, init_node_idx = 0; hmu_tree_node_t *root = NULL, *tp = NULL, *last_tp = NULL; hmu_t *next, *rest; @@ -216,7 +216,7 @@ BH_STATIC hmu_t *alloc_hmu(gc_heap_t *heap, gc_size_t size) /* check normal list at first*/ if (HMU_IS_FC_NORMAL(size)) { /* find a non-empty slot in normal_node_list with good size*/ - init_node_idx = (int) (size >> 3); + init_node_idx = (size >> 3); for (node_idx = init_node_idx; node_idx < HMU_NORMAL_NODE_CNT; node_idx++) { node = heap->kfc_normal_list + node_idx; @@ -233,8 +233,8 @@ BH_STATIC hmu_t *alloc_hmu(gc_heap_t *heap, gc_size_t size) node->next = p->next; bh_assert(((gc_int32)(uintptr_t)hmu_to_obj(p) & 7) == 0); - if ((gc_size_t) node_idx - != init_node_idx&& ((gc_size_t)node_idx << 3) >= size + GC_SMALLEST_SIZE) { /* with bigger size*/ + if ((gc_size_t)node_idx != (uint32)init_node_idx + && ((gc_size_t)node_idx << 3) >= size + GC_SMALLEST_SIZE) { /* with bigger size*/ rest = (hmu_t*) (((char *) p) + size); gci_add_fc(heap, rest, (node_idx << 3) - size); hmu_mark_pinuse(rest); diff --git a/core/shared-lib/mem-alloc/ems/ems_gc.h b/core/shared-lib/mem-alloc/ems/ems_gc.h index 9c705db19..c24fb841e 100644 --- a/core/shared-lib/mem-alloc/ems/ems_gc.h +++ b/core/shared-lib/mem-alloc/ems/ems_gc.h @@ -169,7 +169,7 @@ extern int gc_destroy_with_pool(gc_handle_t handle); * @param size [in] the size of stats * @param mmt [in] type of heap, MMT_SHARED or MMT_INSTANCE */ -extern void* gc_heap_stats(void *heap, int* stats, int size, gc_mm_t mmt); +extern void* gc_heap_stats(void *heap, uint32* stats, int size, gc_mm_t mmt); /** * Set GC threshold factor diff --git a/core/shared-lib/mem-alloc/ems/ems_gc_internal.h b/core/shared-lib/mem-alloc/ems/ems_gc_internal.h index 9ee66921a..94efb60cb 100644 --- a/core/shared-lib/mem-alloc/ems/ems_gc_internal.h +++ b/core/shared-lib/mem-alloc/ems/ems_gc_internal.h @@ -77,7 +77,7 @@ extern void hmu_verify(hmu_t *hmu); #define hmu_obj_size(s) ((s)-OBJ_EXTRA_SIZE) -#define GC_ALIGN_8(s) (((int)(s) + 7) & ~7) +#define GC_ALIGN_8(s) (((uint32)(s) + 7) & (uint32)~7) #define GC_SMALLEST_SIZE GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE + 8) #define GC_GET_REAL_SIZE(x) GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE + (((x) > 8) ? (x): 8)) @@ -86,14 +86,14 @@ extern void hmu_verify(hmu_t *hmu); #define SETBIT(v, offset) (v) |= (1 << (offset)) #define GETBIT(v, offset) ((v) & (1 << (offset)) ? 1 : 0) -#define CLRBIT(v, offset) (v) &= ~(1 << (offset)) +#define CLRBIT(v, offset) (v) &= (uint32)(~(1 << (offset))) #define SETBITS(v, offset, size, value) do { \ - (v) &= ~(((1 << size) - 1) << offset); \ - (v) |= value << offset; \ - } while(0) + (v) &= (uint32)(~(((1 << size) - 1) << offset));\ + (v) |= (uint32)(value << offset); \ + } while(0) #define CLRBITS(v, offset, size) (v) &= ~(((1 << size) - 1) << offset) -#define GETBITS(v, offset, size) (((v) & (((1 << size) - 1) << offset)) >> offset) +#define GETBITS(v, offset, size) (((v) & ((uint32)(((1 << size) - 1) << offset))) >> offset) /*////// gc object layout definition*/ diff --git a/core/shared-lib/mem-alloc/ems/ems_kfc.c b/core/shared-lib/mem-alloc/ems/ems_kfc.c index 8b619fdbb..6a969e9aa 100644 --- a/core/shared-lib/mem-alloc/ems/ems_kfc.c +++ b/core/shared-lib/mem-alloc/ems/ems_kfc.c @@ -41,7 +41,7 @@ int gci_check_platform() gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size) { char *buf_end = buf + buf_size; - char *buf_aligned = (char*) (((uintptr_t) buf + 7) & ~7); + char *buf_aligned = (char*) (((uintptr_t) buf + 7) & (uintptr_t)~7); char *base_addr = buf_aligned + sizeof(gc_heap_t); gc_heap_t *heap = (gc_heap_t*) buf_aligned; gc_size_t heap_max_size; @@ -60,8 +60,8 @@ gc_handle_t gc_init_with_pool(char *buf, gc_size_t buf_size) return NULL; } - base_addr = (char*) (((uintptr_t) base_addr + 7) & ~7) + GC_HEAD_PADDING; - heap_max_size = (buf_end - base_addr) & ~7; + base_addr = (char*) (((uintptr_t) base_addr + 7) & (uintptr_t)~7) + GC_HEAD_PADDING; + heap_max_size = (uint32)(buf_end - base_addr) & (uint32)~7; memset(heap, 0, sizeof *heap); memset(base_addr, 0, heap_max_size); @@ -154,7 +154,7 @@ void gci_verify_heap(gc_heap_t *heap) } #endif -void* gc_heap_stats(void *heap_arg, int* stats, int size, gc_mm_t mmt) +void* gc_heap_stats(void *heap_arg, uint32* stats, int size, gc_mm_t mmt) { (void) mmt; int i; @@ -175,7 +175,7 @@ void* gc_heap_stats(void *heap_arg, int* stats, int size, gc_mm_t mmt) stats[i] = heap->total_gc_count; break; case GC_STAT_TIME: - stats[i] = (int) heap->total_gc_time; + stats[i] = (uint32)heap->total_gc_time; break; default: break; diff --git a/core/shared-lib/platform/CMakeLists.txt b/core/shared-lib/platform/CMakeLists.txt index 0161f67c2..5f0ed6a1f 100755 --- a/core/shared-lib/platform/CMakeLists.txt +++ b/core/shared-lib/platform/CMakeLists.txt @@ -3,7 +3,7 @@ include_directories (./include ../include ./${PLATFORM}) -add_definitions (-D__POSIX__ -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=199309L -D_BSD_SOURCE) +add_definitions (-D__POSIX__ -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200809L -D_BSD_SOURCE) file (GLOB_RECURSE source_all ${PLATFORM}/*.c) add_library (supportlib ${source_all}) diff --git a/core/shared-lib/platform/alios/bh_platform.c b/core/shared-lib/platform/alios/bh_platform.c index 9e0be0bf5..ed9f33561 100644 --- a/core/shared-lib/platform/alios/bh_platform.c +++ b/core/shared-lib/platform/alios/bh_platform.c @@ -4,14 +4,20 @@ */ #include "bh_platform.h" +#include "bh_common.h" #include #include char *bh_strdup(const char *s) { + uint32 size; char *s1 = NULL; - if (s && (s1 = bh_malloc(strlen(s) + 1))) - memcpy(s1, s, strlen(s) + 1); + + if (s) { + size = (uint32)(strlen(s) + 1); + if ((s1 = bh_malloc(size))) + bh_memcpy_s(s1, size, s, size); + } return s1; } diff --git a/core/shared-lib/platform/darwin/bh_platform.c b/core/shared-lib/platform/darwin/bh_platform.c old mode 100644 new mode 100755 index a1c35233e..0c16bf695 --- a/core/shared-lib/platform/darwin/bh_platform.c +++ b/core/shared-lib/platform/darwin/bh_platform.c @@ -4,6 +4,7 @@ */ #include "bh_platform.h" +#include "bh_common.h" #include #include @@ -11,9 +12,14 @@ char *bh_strdup(const char *s) { + uint32 size; char *s1 = NULL; - if (s && (s1 = bh_malloc(strlen(s) + 1))) - memcpy(s1, s, strlen(s) + 1); + + if (s) { + size = (uint32)(strlen(s) + 1); + if ((s1 = bh_malloc(size))) + bh_memcpy_s(s1, size, s, size); + } return s1; } @@ -23,11 +29,11 @@ int bh_platform_init() } char* -bh_read_file_to_buffer(const char *filename, int *ret_size) +bh_read_file_to_buffer(const char *filename, uint32 *ret_size) { char *buffer; int file; - int file_size, read_size; + uint32 file_size, read_size; struct stat stat_buf; if (!filename || !ret_size) { @@ -48,7 +54,7 @@ bh_read_file_to_buffer(const char *filename, int *ret_size) return NULL; } - file_size = stat_buf.st_size; + file_size = (uint32)stat_buf.st_size; if (!(buffer = bh_malloc(file_size))) { printf("Read file to buffer failed: alloc memory failed.\n"); @@ -56,7 +62,7 @@ bh_read_file_to_buffer(const char *filename, int *ret_size) return NULL; } - read_size = read(file, buffer, file_size); + read_size = (uint32)read(file, buffer, file_size); close(file); if (read_size < file_size) { diff --git a/core/shared-lib/platform/darwin/bh_platform.h b/core/shared-lib/platform/darwin/bh_platform.h index b25e1a88e..7c27ce081 100644 --- a/core/shared-lib/platform/darwin/bh_platform.h +++ b/core/shared-lib/platform/darwin/bh_platform.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -98,7 +99,7 @@ int b_strcpy_s(char * s1, size_t s1max, const char * s2); int fopen_s(FILE ** pFile, const char *filename, const char *mode); -char *bh_read_file_to_buffer(const char *filename, int *ret_size); +char *bh_read_file_to_buffer(const char *filename, uint32 *ret_size); char *bh_strdup(const char *s); diff --git a/core/shared-lib/platform/darwin/bh_thread.c b/core/shared-lib/platform/darwin/bh_thread.c index 8619a7ad0..abf736806 100644 --- a/core/shared-lib/platform/darwin/bh_thread.c +++ b/core/shared-lib/platform/darwin/bh_thread.c @@ -56,7 +56,7 @@ void vm_thread_sys_destroy(void) typedef struct { thread_start_routine_t start; void* stack; - int stack_size; + uint32 stack_size; void* arg; } thread_wrapper_arg; @@ -64,7 +64,7 @@ static void *vm_thread_wrapper(void *arg) { thread_wrapper_arg * targ = arg; LOG_VERBOSE("THREAD CREATE 0x%08x\n", &targ); - targ->stack = (void *)((uintptr_t)(&arg) & ~0xfff); + targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff); _vm_tls_put(1, targ); targ->start(targ->arg); bh_free(targ); @@ -73,7 +73,7 @@ static void *vm_thread_wrapper(void *arg) } int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, - void *arg, unsigned int stack_size, int prio) + void *arg, unsigned int stack_size, int prio) { pthread_attr_t tattr; thread_wrapper_arg *targ; @@ -114,7 +114,7 @@ int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, } int _vm_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg, - unsigned int stack_size) + unsigned int stack_size) { return _vm_thread_create_with_prio(tid, start, arg, stack_size, BH_THREAD_DEFAULT_PRIORITY); @@ -261,7 +261,7 @@ int _vm_sem_wait(korp_sem *sem) bh_assert(sem); - if (mills == BHT_WAIT_FOREVER) { + if (mills == (int)BHT_WAIT_FOREVER) { ret = sem_wait(sem); } else { @@ -330,8 +330,8 @@ static void msec_nsec_to_abstime(struct timespec *ts, int64 msec, int32 nsec) gettimeofday(&tv, NULL); - ts->tv_sec = tv.tv_sec + msec / 1000; - ts->tv_nsec = tv.tv_usec * 1000 + (msec % 1000) * 1000000 + nsec; + ts->tv_sec = (long int)(tv.tv_sec + msec / 1000); + ts->tv_nsec = (long int)(tv.tv_usec * 1000 + (msec % 1000) * 1000000 + nsec); if (ts->tv_nsec >= 1000000000L) { ts->tv_sec++; @@ -344,7 +344,7 @@ int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills) int ret; struct timespec abstime; - if (mills == BHT_WAIT_FOREVER) + if (mills == (int)BHT_WAIT_FOREVER) ret = pthread_cond_wait(cond, mutex); else { msec_nsec_to_abstime(&abstime, mills, 0); diff --git a/core/shared-lib/platform/darwin/bh_time.c b/core/shared-lib/platform/darwin/bh_time.c index b8d9e8f8c..698cdec24 100644 --- a/core/shared-lib/platform/darwin/bh_time.c +++ b/core/shared-lib/platform/darwin/bh_time.c @@ -16,7 +16,7 @@ */ uint64 _bh_time_get_tick_millisecond() { - return sysconf(_SC_CLK_TCK); + return (uint64)sysconf(_SC_CLK_TCK); } /* @@ -30,12 +30,12 @@ uint64 _bh_time_get_boot_millisecond() return 0; } - return ((uint64) ts.tv_sec) * 1000 + ts.tv_nsec / (1000 * 1000); + return ((uint64) ts.tv_sec) * 1000 + ((uint64)ts.tv_nsec) / (1000 * 1000); } uint32 bh_get_tick_sec() { - return _bh_time_get_boot_millisecond() / 1000; + return (uint32)(_bh_time_get_boot_millisecond() / 1000); } /* @@ -48,12 +48,13 @@ uint64 _bh_time_get_millisecond_from_1970() ftime(&tp); return ((uint64) tp.time) * 1000 + tp.millitm - - (tp.dstflag == 0 ? 0 : 60 * 60 * 1000) + tp.timezone * 60 * 1000; + - (tp.dstflag == 0 ? 0 : 60 * 60 * 1000) + + ((uint64)tp.timezone) * 60 * 1000; } size_t _bh_time_strftime(char *s, size_t max, const char *format, int64 time) { - time_t time_sec = time / 1000; + time_t time_sec = (time_t)(time / 1000); struct timeb tp; struct tm *ltp; diff --git a/core/shared-lib/platform/linux-sgx/bh_definition.c b/core/shared-lib/platform/linux-sgx/bh_definition.c index 5460c5a5d..eba9ad6a8 100644 --- a/core/shared-lib/platform/linux-sgx/bh_definition.c +++ b/core/shared-lib/platform/linux-sgx/bh_definition.c @@ -52,16 +52,3 @@ int b_strcpy_s(char * s1, size_t s1max, const char * s2) return 0; } -int fopen_s(FILE ** pFile, const char *filename, const char *mode) -{ - if (NULL == pFile || NULL == filename || NULL == mode) { - return -1; - } - - *pFile = fopen(filename, mode); - - if (NULL == *pFile) - return -1; - - return 0; -} diff --git a/core/shared-lib/platform/linux-sgx/bh_platform.c b/core/shared-lib/platform/linux-sgx/bh_platform.c index 10c2aecf4..298f43050 100644 --- a/core/shared-lib/platform/linux-sgx/bh_platform.c +++ b/core/shared-lib/platform/linux-sgx/bh_platform.c @@ -15,12 +15,35 @@ static bh_print_function_t print_function = NULL; char *bh_strdup(const char *s) { + uint32 size; char *s1 = NULL; - if (s && (s1 = bh_malloc(strlen(s) + 1))) - memcpy(s1, s, strlen(s) + 1); + + if (s) { + size = (uint32)(strlen(s) + 1); + if ((s1 = bh_malloc(size))) + bh_memcpy_s(s1, size, s, size); + } return s1; } +const unsigned short ** __ctype_b_loc(void) +{ + /* TODO */ + return NULL; +} + +const int32_t ** __ctype_toupper_loc(void) +{ + /* TODO */ + return NULL; +} + +const int32_t ** __ctype_tolower_loc(void) +{ + /* TODO */ + return NULL; +} + int bh_platform_init() { return 0; diff --git a/core/shared-lib/platform/linux-sgx/bh_platform.h b/core/shared-lib/platform/linux-sgx/bh_platform.h index e4f726b6c..9973c0289 100644 --- a/core/shared-lib/platform/linux-sgx/bh_platform.h +++ b/core/shared-lib/platform/linux-sgx/bh_platform.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#include #include #ifdef __cplusplus diff --git a/core/shared-lib/platform/linux-sgx/bh_thread.c b/core/shared-lib/platform/linux-sgx/bh_thread.c index cfd6aff25..f29c90607 100644 --- a/core/shared-lib/platform/linux-sgx/bh_thread.c +++ b/core/shared-lib/platform/linux-sgx/bh_thread.c @@ -20,14 +20,14 @@ void vm_thread_sys_destroy(void) } int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, - void *arg, unsigned int stack_size, int prio) + void *arg, unsigned int stack_size, int prio) { return BHT_ERROR; // return BHT_OK; } int _vm_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg, - unsigned int stack_size) + unsigned int stack_size) { return _vm_thread_create_with_prio(tid, start, arg, stack_size, BH_THREAD_DEFAULT_PRIORITY); diff --git a/core/shared-lib/platform/linux/bh_platform.c b/core/shared-lib/platform/linux/bh_platform.c index a1c35233e..0c16bf695 100755 --- a/core/shared-lib/platform/linux/bh_platform.c +++ b/core/shared-lib/platform/linux/bh_platform.c @@ -4,6 +4,7 @@ */ #include "bh_platform.h" +#include "bh_common.h" #include #include @@ -11,9 +12,14 @@ char *bh_strdup(const char *s) { + uint32 size; char *s1 = NULL; - if (s && (s1 = bh_malloc(strlen(s) + 1))) - memcpy(s1, s, strlen(s) + 1); + + if (s) { + size = (uint32)(strlen(s) + 1); + if ((s1 = bh_malloc(size))) + bh_memcpy_s(s1, size, s, size); + } return s1; } @@ -23,11 +29,11 @@ int bh_platform_init() } char* -bh_read_file_to_buffer(const char *filename, int *ret_size) +bh_read_file_to_buffer(const char *filename, uint32 *ret_size) { char *buffer; int file; - int file_size, read_size; + uint32 file_size, read_size; struct stat stat_buf; if (!filename || !ret_size) { @@ -48,7 +54,7 @@ bh_read_file_to_buffer(const char *filename, int *ret_size) return NULL; } - file_size = stat_buf.st_size; + file_size = (uint32)stat_buf.st_size; if (!(buffer = bh_malloc(file_size))) { printf("Read file to buffer failed: alloc memory failed.\n"); @@ -56,7 +62,7 @@ bh_read_file_to_buffer(const char *filename, int *ret_size) return NULL; } - read_size = read(file, buffer, file_size); + read_size = (uint32)read(file, buffer, file_size); close(file); if (read_size < file_size) { diff --git a/core/shared-lib/platform/linux/bh_platform.h b/core/shared-lib/platform/linux/bh_platform.h index ddd77a2fc..3d38ebf4e 100644 --- a/core/shared-lib/platform/linux/bh_platform.h +++ b/core/shared-lib/platform/linux/bh_platform.h @@ -20,8 +20,9 @@ #include #include #include -#include #include +#include +#include #include #include #include @@ -98,7 +99,7 @@ int b_strcpy_s(char * s1, size_t s1max, const char * s2); int fopen_s(FILE ** pFile, const char *filename, const char *mode); -char *bh_read_file_to_buffer(const char *filename, int *ret_size); +char *bh_read_file_to_buffer(const char *filename, uint32 *ret_size); char *bh_strdup(const char *s); diff --git a/core/shared-lib/platform/linux/bh_thread.c b/core/shared-lib/platform/linux/bh_thread.c index de865a3c4..8160fb044 100755 --- a/core/shared-lib/platform/linux/bh_thread.c +++ b/core/shared-lib/platform/linux/bh_thread.c @@ -56,7 +56,7 @@ void vm_thread_sys_destroy(void) typedef struct { thread_start_routine_t start; void* stack; - int stack_size; + uint32 stack_size; void* arg; } thread_wrapper_arg; @@ -64,7 +64,7 @@ static void *vm_thread_wrapper(void *arg) { thread_wrapper_arg * targ = arg; LOG_VERBOSE("THREAD CREATE 0x%08x\n", &targ); - targ->stack = (void *)((uintptr_t)(&arg) & ~0xfff); + targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff); _vm_tls_put(1, targ); targ->start(targ->arg); bh_free(targ); @@ -73,7 +73,7 @@ static void *vm_thread_wrapper(void *arg) } int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, - void *arg, unsigned int stack_size, int prio) + void *arg, unsigned int stack_size, int prio) { pthread_attr_t tattr; thread_wrapper_arg *targ; @@ -114,7 +114,7 @@ int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, } int _vm_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg, - unsigned int stack_size) + unsigned int stack_size) { return _vm_thread_create_with_prio(tid, start, arg, stack_size, BH_THREAD_DEFAULT_PRIORITY); @@ -261,7 +261,7 @@ int _vm_sem_reltimedwait(korp_sem *sem, int mills) bh_assert(sem); - if (mills == BHT_WAIT_FOREVER) { + if (mills == (int)BHT_WAIT_FOREVER) { ret = sem_wait(sem); } else { @@ -329,8 +329,8 @@ static void msec_nsec_to_abstime(struct timespec *ts, int64 msec, int32 nsec) gettimeofday(&tv, NULL); - ts->tv_sec = tv.tv_sec + msec / 1000; - ts->tv_nsec = tv.tv_usec * 1000 + (msec % 1000) * 1000000 + nsec; + ts->tv_sec = (long int)(tv.tv_sec + msec / 1000); + ts->tv_nsec = (long int)(tv.tv_usec * 1000 + (msec % 1000) * 1000000 + nsec); if (ts->tv_nsec >= 1000000000L) { ts->tv_sec++; @@ -343,7 +343,7 @@ int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills) int ret; struct timespec abstime; - if (mills == BHT_WAIT_FOREVER) + if (mills == (int)BHT_WAIT_FOREVER) ret = pthread_cond_wait(cond, mutex); else { msec_nsec_to_abstime(&abstime, mills, 0); diff --git a/core/shared-lib/platform/linux/bh_time.c b/core/shared-lib/platform/linux/bh_time.c index b8d9e8f8c..698cdec24 100755 --- a/core/shared-lib/platform/linux/bh_time.c +++ b/core/shared-lib/platform/linux/bh_time.c @@ -16,7 +16,7 @@ */ uint64 _bh_time_get_tick_millisecond() { - return sysconf(_SC_CLK_TCK); + return (uint64)sysconf(_SC_CLK_TCK); } /* @@ -30,12 +30,12 @@ uint64 _bh_time_get_boot_millisecond() return 0; } - return ((uint64) ts.tv_sec) * 1000 + ts.tv_nsec / (1000 * 1000); + return ((uint64) ts.tv_sec) * 1000 + ((uint64)ts.tv_nsec) / (1000 * 1000); } uint32 bh_get_tick_sec() { - return _bh_time_get_boot_millisecond() / 1000; + return (uint32)(_bh_time_get_boot_millisecond() / 1000); } /* @@ -48,12 +48,13 @@ uint64 _bh_time_get_millisecond_from_1970() ftime(&tp); return ((uint64) tp.time) * 1000 + tp.millitm - - (tp.dstflag == 0 ? 0 : 60 * 60 * 1000) + tp.timezone * 60 * 1000; + - (tp.dstflag == 0 ? 0 : 60 * 60 * 1000) + + ((uint64)tp.timezone) * 60 * 1000; } size_t _bh_time_strftime(char *s, size_t max, const char *format, int64 time) { - time_t time_sec = time / 1000; + time_t time_sec = (time_t)(time / 1000); struct timeb tp; struct tm *ltp; diff --git a/core/shared-lib/platform/vxworks/bh_definition.c b/core/shared-lib/platform/vxworks/bh_definition.c index 1af69e134..4cdf98259 100644 --- a/core/shared-lib/platform/vxworks/bh_definition.c +++ b/core/shared-lib/platform/vxworks/bh_definition.c @@ -41,8 +41,9 @@ int b_strcat_s(char * s1, size_t s1max, const char * s2) int b_strcpy_s(char * s1, size_t s1max, const char * s2) { - if (NULL == s1|| NULL == s2 - || s1max < (strlen(s2) + 1) || s1max > RSIZE_MAX) { + if (NULL == s1 || NULL == s2 + || s1max < (strlen(s2) + 1) + || s1max > RSIZE_MAX) { return -1; } diff --git a/core/shared-lib/platform/vxworks/bh_platform.c b/core/shared-lib/platform/vxworks/bh_platform.c index 698c8574a..6f0eddfd7 100644 --- a/core/shared-lib/platform/vxworks/bh_platform.c +++ b/core/shared-lib/platform/vxworks/bh_platform.c @@ -4,6 +4,7 @@ */ #include "bh_platform.h" +#include "bh_common.h" #include #include #include @@ -15,9 +16,14 @@ char *bh_strdup(const char *s) { + uint32 size; char *s1 = NULL; - if (s && (s1 = bh_malloc(strlen(s) + 1))) - memcpy(s1, s, strlen(s) + 1); + + if (s) { + size = (uint32)(strlen(s) + 1); + if ((s1 = bh_malloc(size))) + bh_memcpy_s(s1, size, s, size); + } return s1; } @@ -27,11 +33,11 @@ int bh_platform_init() } char* -bh_read_file_to_buffer(const char *filename, int *ret_size) +bh_read_file_to_buffer(const char *filename, uint32 *ret_size) { char *buffer; int file; - int file_size, read_size; + uint32 file_size, read_size; struct stat stat_buf; if (!filename || !ret_size) { @@ -52,7 +58,7 @@ bh_read_file_to_buffer(const char *filename, int *ret_size) return NULL; } - file_size = stat_buf.st_size; + file_size = (uint32)stat_buf.st_size; if (!(buffer = bh_malloc(file_size))) { printf("Read file to buffer failed: alloc memory failed.\n"); @@ -60,7 +66,7 @@ bh_read_file_to_buffer(const char *filename, int *ret_size) return NULL; } - read_size = read(file, buffer, file_size); + read_size = (uint32)read(file, buffer, file_size); close(file); if (read_size < file_size) { diff --git a/core/shared-lib/platform/vxworks/bh_platform.h b/core/shared-lib/platform/vxworks/bh_platform.h index acc8ae4da..2f4047ec4 100644 --- a/core/shared-lib/platform/vxworks/bh_platform.h +++ b/core/shared-lib/platform/vxworks/bh_platform.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -96,7 +97,7 @@ int b_memcpy_s(void * s1, unsigned int s1max, const void * s2, int b_strcat_s(char * s1, size_t s1max, const char * s2); int b_strcpy_s(char * s1, size_t s1max, const char * s2); -char *bh_read_file_to_buffer(const char *filename, int *ret_size); +char *bh_read_file_to_buffer(const char *filename, uint32 *ret_size); char *bh_strdup(const char *s); diff --git a/core/shared-lib/platform/vxworks/bh_thread.c b/core/shared-lib/platform/vxworks/bh_thread.c index b8ddb97d0..3b51596fd 100644 --- a/core/shared-lib/platform/vxworks/bh_thread.c +++ b/core/shared-lib/platform/vxworks/bh_thread.c @@ -56,7 +56,7 @@ void vm_thread_sys_destroy(void) typedef struct { thread_start_routine_t start; void* stack; - int stack_size; + uint32 stack_size; void* arg; } thread_wrapper_arg; @@ -64,7 +64,7 @@ static void *vm_thread_wrapper(void *arg) { thread_wrapper_arg * targ = arg; LOG_VERBOSE("THREAD CREATE 0x%08x\n", &targ); - targ->stack = (void *)((uintptr_t)(&arg) & ~0xfff); + targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff); _vm_tls_put(1, targ); targ->start(targ->arg); bh_free(targ); @@ -73,7 +73,7 @@ static void *vm_thread_wrapper(void *arg) } int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, - void *arg, unsigned int stack_size, int prio) + void *arg, unsigned int stack_size, int prio) { pthread_attr_t tattr; thread_wrapper_arg *targ; @@ -114,7 +114,7 @@ int _vm_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, } int _vm_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg, - unsigned int stack_size) + unsigned int stack_size) { return _vm_thread_create_with_prio(tid, start, arg, stack_size, BH_THREAD_DEFAULT_PRIORITY); @@ -261,7 +261,7 @@ int _vm_sem_reltimedwait(korp_sem *sem, int mills) bh_assert(sem); - if (mills == BHT_WAIT_FOREVER) { + if (mills == (int)BHT_WAIT_FOREVER) { ret = sem_wait(sem); } else { @@ -329,8 +329,8 @@ static void msec_nsec_to_abstime(struct timespec *ts, int64 msec, int32 nsec) gettimeofday(&tv, NULL); - ts->tv_sec = tv.tv_sec + msec / 1000; - ts->tv_nsec = tv.tv_usec * 1000 + (msec % 1000) * 1000000 + nsec; + ts->tv_sec = (long int)(tv.tv_sec + msec / 1000); + ts->tv_nsec = (long int)(tv.tv_usec * 1000 + (msec % 1000) * 1000000 + nsec); if (ts->tv_nsec >= 1000000000L) { ts->tv_sec++; @@ -343,7 +343,7 @@ int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills) int ret; struct timespec abstime; - if (mills == BHT_WAIT_FOREVER) + if (mills == (int)BHT_WAIT_FOREVER) ret = pthread_cond_wait(cond, mutex); else { msec_nsec_to_abstime(&abstime, mills, 0); diff --git a/core/shared-lib/platform/vxworks/bh_time.c b/core/shared-lib/platform/vxworks/bh_time.c index 696c994d3..fefa0496a 100644 --- a/core/shared-lib/platform/vxworks/bh_time.c +++ b/core/shared-lib/platform/vxworks/bh_time.c @@ -15,7 +15,7 @@ */ uint64 _bh_time_get_tick_millisecond() { - return sysconf(_SC_CLK_TCK); + return (uint64)sysconf(_SC_CLK_TCK); } /* @@ -29,12 +29,12 @@ uint64 _bh_time_get_boot_millisecond() return 0; } - return ((uint64) ts.tv_sec) * 1000 + ts.tv_nsec / (1000 * 1000); + return ((uint64) ts.tv_sec) * 1000 + ((uint64)ts.tv_nsec) / (1000 * 1000); } uint32 bh_get_tick_sec() { - return _bh_time_get_boot_millisecond() / 1000; + return (uint32)(_bh_time_get_boot_millisecond() / 1000); } /* @@ -49,12 +49,12 @@ uint64 _bh_time_get_millisecond_from_1970() return 0; } - return ((uint64) ts.tv_sec) * 1000 + ts.tv_nsec / (1000 * 1000); + return ((uint64) ts.tv_sec) * 1000 + ((uint64)ts.tv_nsec) / (1000 * 1000); } size_t _bh_time_strftime(char *s, size_t max, const char *format, int64 time) { - time_t time_sec = time / 1000; + time_t time_sec = (time_t)(time / 1000); struct tm *ltp; ltp = localtime(&time_sec); diff --git a/core/shared-lib/platform/zephyr/bh_platform.c b/core/shared-lib/platform/zephyr/bh_platform.c index dd0e6b50e..b495a722c 100755 --- a/core/shared-lib/platform/zephyr/bh_platform.c +++ b/core/shared-lib/platform/zephyr/bh_platform.c @@ -4,14 +4,20 @@ */ #include "bh_platform.h" +#include "bh_common.h" #include #include char *bh_strdup(const char *s) { + uint32 size; char *s1 = NULL; - if (s && (s1 = bh_malloc(strlen(s) + 1))) - memcpy(s1, s, strlen(s) + 1); + + if (s) { + size = (uint32)(strlen(s) + 1); + if ((s1 = bh_malloc(size))) + bh_memcpy_s(s1, size, s, size); + } return s1; } diff --git a/core/shared-lib/platform/zephyr/bh_platform.h b/core/shared-lib/platform/zephyr/bh_platform.h index 44614a150..441643118 100644 --- a/core/shared-lib/platform/zephyr/bh_platform.h +++ b/core/shared-lib/platform/zephyr/bh_platform.h @@ -19,7 +19,9 @@ #include #include #include +#include #include +#include #ifndef CONFIG_NET_BUF_USER_DATA_SIZE #define CONFIG_NET_BUF_USER_DATA_SIZE 0 #endif diff --git a/core/shared-lib/shared_lib.cmake b/core/shared-lib/shared_lib.cmake deleted file mode 100644 index e933d1162..000000000 --- a/core/shared-lib/shared_lib.cmake +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -include (${CMAKE_CURRENT_LIST_DIR}/utils/shared_utils.cmake) -include (${CMAKE_CURRENT_LIST_DIR}/mem-alloc/mem_alloc.cmake) -include (${CMAKE_CURRENT_LIST_DIR}/platform/${PLATFORM}/shared_platform.cmake) diff --git a/core/shared-lib/utils/bh_log.c b/core/shared-lib/utils/bh_log.c index 0a7de0339..39d89781d 100644 --- a/core/shared-lib/utils/bh_log.c +++ b/core/shared-lib/utils/bh_log.c @@ -94,7 +94,7 @@ void _bh_log_vprintf(const char *fmt, va_list ap) if (fmt && (cur_log_enabled = is_log_enabled(fmt))) { char buf[32]; bh_time_strftime(buf, 32, "%Y-%m-%d %H:%M:%S", - bh_time_get_millisecond_from_1970()); + (int64)bh_time_get_millisecond_from_1970()); bh_log_emit_helper("\n[%s - %X]: ", buf, (int) self); /* Strip the "Vn." prefix. */ diff --git a/core/shared-lib/utils/bh_queue.c b/core/shared-lib/utils/bh_queue.c index 1a4379959..cd6a58166 100644 --- a/core/shared-lib/utils/bh_queue.c +++ b/core/shared-lib/utils/bh_queue.c @@ -13,7 +13,7 @@ typedef struct _bh_queue_node { struct _bh_queue_node * next; struct _bh_queue_node * prev; unsigned short tag; - unsigned long len; + unsigned int len; void * body; bh_msg_cleaner msg_cleaner; } bh_queue_node; @@ -35,7 +35,7 @@ char * bh_message_payload(bh_message_t message) return message->body; } -int bh_message_payload_len(bh_message_t message) +uint32 bh_message_payload_len(bh_message_t message) { return message->len; } @@ -230,7 +230,7 @@ void bh_queue_enter_loop_run(bh_queue *queue, return; while (!queue->exit_loop_run) { - bh_queue_node * message = bh_get_msg(queue, BH_WAIT_FOREVER); + bh_queue_node * message = bh_get_msg(queue, (int)BH_WAIT_FOREVER); if (message) { handle_cb(message, arg); diff --git a/core/shared-lib/utils/runtime_timer.c b/core/shared-lib/utils/runtime_timer.c index 341e434f8..31820780e 100644 --- a/core/shared-lib/utils/runtime_timer.c +++ b/core/shared-lib/utils/runtime_timer.c @@ -55,7 +55,7 @@ uint32 bh_get_elpased_ms(uint32 * last_system_clock) } static app_timer_t * remove_timer_from(timer_ctx_t ctx, uint32 timer_id, - bool active_list) + bool active_list) { vm_mutex_lock(&ctx->mutex); app_timer_t ** head; @@ -94,7 +94,7 @@ static app_timer_t * remove_timer_from(timer_ctx_t ctx, uint32 timer_id, } static app_timer_t * remove_timer(timer_ctx_t ctx, uint32 timer_id, - bool * active) + bool * active) { app_timer_t* t = remove_timer_from(ctx, timer_id, true); if (t) { @@ -196,8 +196,8 @@ void release_timer_list(app_timer_t ** p_list) */ timer_ctx_t create_timer_ctx(timer_callback_f timer_handler, - check_timer_expiry_f expiery_checker, int prealloc_num, - unsigned int owner) + check_timer_expiry_f expiery_checker, int prealloc_num, + unsigned int owner) { timer_ctx_t ctx = (timer_ctx_t) bh_malloc(sizeof(struct _timer_ctx)); if (ctx == NULL) @@ -252,19 +252,6 @@ void destroy_timer_ctx(timer_ctx_t ctx) bh_free(ctx); } -void timer_ctx_set_lock(timer_ctx_t ctx, bool lock) -{ - if (lock) - vm_mutex_lock(&ctx->mutex); - else - vm_mutex_unlock(&ctx->mutex); -} - -void * timer_ctx_get_lock(timer_ctx_t ctx) -{ - return &ctx->mutex; -} - unsigned int timer_ctx_get_owner(timer_ctx_t ctx) { return ctx->owner; @@ -279,14 +266,14 @@ void add_idle_timer(timer_ctx_t ctx, app_timer_t * timer) } uint32 sys_create_timer(timer_ctx_t ctx, int interval, bool is_period, - bool auto_start) + bool auto_start) { app_timer_t *timer; if (ctx->pre_allocated) { if (ctx->free_timers == NULL) - return -1; + return (uint32)-1; else { timer = ctx->free_timers; ctx->free_timers = timer->next; @@ -294,16 +281,16 @@ uint32 sys_create_timer(timer_ctx_t ctx, int interval, bool is_period, } else { timer = (app_timer_t*) bh_malloc(sizeof(app_timer_t)); if (timer == NULL) - return -1; + return (uint32)-1; } memset(timer, 0, sizeof(*timer)); ctx->g_max_id++; - if (ctx->g_max_id == -1) + if (ctx->g_max_id == (uint32)-1) ctx->g_max_id++; timer->id = ctx->g_max_id; - timer->interval = interval; + timer->interval = (uint32)interval; timer->is_periodic = is_period; if (auto_start) @@ -347,7 +334,7 @@ bool sys_timer_restart(timer_ctx_t ctx, uint32 timer_id, int interval) return false; if (interval > 0) - t->interval = interval; + t->interval = (uint32)interval; reschedule_timer(ctx, t); @@ -393,7 +380,7 @@ int get_expiry_ms(timer_ctx_t ctx) if (ctx->g_app_timers == NULL) ms_to_next_expiry = 7 * 24 * 60 * 60 * 1000; // 1 week else if (ctx->g_app_timers->expiry >= now) - ms_to_next_expiry = ctx->g_app_timers->expiry - now; + ms_to_next_expiry = (int)(ctx->g_app_timers->expiry - now); else ms_to_next_expiry = 0; vm_mutex_unlock(&ctx->mutex); diff --git a/core/shared-lib/utils/runtime_timer.h b/core/shared-lib/utils/runtime_timer.h index eb0ea9bc7..4e8dfe02f 100644 --- a/core/shared-lib/utils/runtime_timer.h +++ b/core/shared-lib/utils/runtime_timer.h @@ -22,8 +22,6 @@ typedef void (*check_timer_expiry_f)(timer_ctx_t ctx); timer_ctx_t create_timer_ctx(timer_callback_f timer_handler, check_timer_expiry_f, int prealloc_num, unsigned int owner); void destroy_timer_ctx(timer_ctx_t); -void timer_ctx_set_lock(timer_ctx_t ctx, bool lock); -void * timer_ctx_get_lock(timer_ctx_t ctx); unsigned int timer_ctx_get_owner(timer_ctx_t ctx); uint32 sys_create_timer(timer_ctx_t ctx, int interval, bool is_period, diff --git a/doc/building.md b/doc/building.md index ff1be6403..6f7a2958c 100644 --- a/doc/building.md +++ b/doc/building.md @@ -12,7 +12,7 @@ sudo apt install lib32gcc-5-dev g++-multilib ``` Or in Fedora: ``` Bash -sudo dnf install glibc-devel.i686 +sudo dnf install glibc-devel.i686 ``` After installing dependencies, build the source code: @@ -23,6 +23,48 @@ cd build cmake .. make ``` +Note: +The WASI feature is enabled by default, if we want to disable it, please run: +``` Bash +cmake .. -DWASM_ENALBE_WASI=0 +``` + +Linux SGX (Intel Software Guard Extention) +------------------------- +First of all please install library dependencies of lib gcc. +Use installation commands below for Ubuntu Linux: +``` Bash +sudo apt install lib32gcc-5-dev g++-multilib +``` +Or in Fedora: +``` Bash +sudo dnf install glibc-devel.i686 +``` + +And then install the [Intel SGX SDK](https://software.intel.com/en-us/sgx/sdk). + +After installing dependencies, build the source code: +``` Bash +cd core/iwasm/products/linux-sgx/ +mkdir build +cd build +cmake .. +make +``` +This builds the libraries used by SGX enclave sample, the generated file libvmlib.a and libextlib.a will be copied to enclave-sample folder. + +Then build the enclave sample: +``` Bash +cd enclave-sample +make +``` +The binary file app will be generated. + +To run the sample: +``` Bash +source /environment +./app +``` Mac ------------------------- @@ -69,6 +111,14 @@ Copy the generated iwasm executable, the test WASM binary as well as the needed shared libraries (libc.so.1, libllvm.so.1 or libgnu.so.1 depending on the VSB, libunix.so.1) to a supported file system (eg: romfs). +WASI +------------------------- +On Linux / Mac / VxWorks platforms, WASI is enabled by default. To build iwasm without wasi support, pass an option when you run cmake: +``` +cmake .. -DWASM_ENABLE_WASI=0 +make +``` + Zephyr ------------------------- You need to download the Zephyr source code first and embed WAMR into it. @@ -84,6 +134,7 @@ source ../../../zephyr-env.sh cmake -GNinja -DBOARD=qemu_x86 .. ninja ``` + AliOS-Things ------------------------- 1. a developerkit board id needed for testing @@ -174,63 +225,64 @@ int main(int argc, char **argv) } ``` -There are three methods to build a WASM binary. They are Emscripten, the clang compiler and Docker. - -## Use Emscripten tool - -A method to build a WASM binary is to use Emscripten tool ```emcc```. -Assuming you are using Linux, you may install emcc from Emscripten EMSDK following the steps below: - -``` -git clone https://github.com/emscripten-core/emsdk.git -emsdk install latest -emsdk activate latest -``` -source ```./emsdk_env.sh```. -The Emscripten website provides other installation methods beyond Linux. - -Use the emcc command below to build the WASM C source code into the WASM binary. -``` Bash -emcc -g -O3 *.c -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \ - -s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 -o test.wasm -``` -You will get ```test.wasm``` which is the WASM app binary. +There are several methods to build a WASM binary. They are the clang compiler, Docker, Emscripten and so on. ## Use clang compiler -Another method to build a WASM binary is to use clang compiler```clang-8```. +The recommended method to build a WASM binary is to use clang compiler ```clang-8```. You can refer to [apt.llvm.org](https://apt.llvm.org) for the detailed instructions. Here are referenced steps to install clang-8 in Ubuntu 16.04 and Ubuntu 18.04. -Add source to your system source list from llvm website, for ubuntu16.04, add following lines to /etc/apt/sources.list: +(1) Add source to your system source list from llvm website + +For Ubuntu 16.04, add the following lines to /etc/apt/sources.list: ```Bash deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial main -deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial main # 7 -deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-7 main -deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-7 main # 8 +deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial main +# 8 deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main +# 9 +deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main +deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main ``` -Download and install clang-8 tool-chain using following commands: +For Ubuntu 18.04, add the following lines to /etc/apt/sources.list: ```Bash -wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - +# i386 not available +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic main +# 8 +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main +# 9 +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main + +(2) Download and install clang-8 tool-chain using following commands: + +```Bash +sudo wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - +# Fingerprint: 6084 F3CF 814B 57C1 CF12 EFD5 15CF 4D18 AF4F 7421 sudo apt-get update sudo apt-get install llvm-8 lld-8 clang-8 ``` -Create a soft link under /usr/bin: +(3) Create a soft link under /usr/bin: ```Bash cd /usr/bin sudo ln -s wasm-ld-8 wasm-ld ``` -Use the clang-8 command below to build the WASM C source code into the WASM binary. +(4) Use the clang-8 command below to build the WASM C source code into the WASM binary. ```Bash -clang-8 --target=wasm32 -O3 -Wl,--initial-memory=131072,--allow-undefined,--export=main, ---no-threads,--strip-all,--no-entry -nostdlib -o test.wasm test.c +clang-8 --target=wasm32 -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -Wl,--allow-undefined,--export=main \ + -Wl,--strip-all,--no-entry -nostdlib \ + -o test.wasm test.c ``` You will get ```test.wasm``` which is the WASM app binary. @@ -255,19 +307,56 @@ You will get ```hello_world``` which is the WASM app binary. For more details about wamr toolchain, please refer to [test-tools/toolchain](../test-tools/toolchain/README.md). +## Use wasi-sdk + +To build a wasm application with wasi support, wasi-sdk is required. Download the [wasi-sdk](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive, then you can use it to build your application: +```Bash +/path/to/wasi-sdk/bin/clang test.c -o test.wasm +``` + +You will get ```test.wasm``` which is the WASM app binary. + ## Using Docker -The last method availble is using [Docker](https://www.docker.com/). We assume you've already configured Docker (see Platform section above) and have a running interactive shell. Currently the Dockerfile only supports compiling apps with clang, with Emscripten planned for the future. +Another method availble is using [Docker](https://www.docker.com/). We assume you've already configured Docker (see Platform section above) and have a running interactive shell. Currently the Dockerfile only supports compiling apps with clang, with Emscripten planned for the future. Use the clang-8 command below to build the WASM C source code into the WASM binary. ```Bash -clang-8 --target=wasm32 -O3 -Wl,--initial-memory=131072,--allow-undefined,--export=main, ---no-threads,--strip-all,--no-entry -nostdlib -o test.wasm test.c +clang-8 --target=wasm32 -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -Wl,--allow-undefined,--export=main \ + -Wl,--strip-all,--no-entry -nostdlib \ + -o test.wasm test.c ``` You will get ```test.wasm``` which is the WASM app binary. +## Use Emscripten tool + +The last method to build a WASM binary is to use Emscripten tool ```emcc```. +Assuming you are using Linux, you may install emcc from Emscripten EMSDK following the steps below: + +``` +git clone https://github.com/emscripten-core/emsdk.git +cd emsdk +./emsdk install latest-fastcomp +./emsdk activate latest-fastcomp +``` +The Emscripten website provides other installation methods beyond Linux. + +Use the emcc command below to build the WASM C source code into the WASM binary. +``` Bash +cd emsdk +source emsdk_env.sh (or add it to ~/.bashrc if you don't want to run it each time) +cd +EMCC_ONLY_FORCED_STDLIBS=1 emcc -g -O3 -s WASM=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0 \ + -s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 \ + -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \ + -s "EXPORTED_FUNCTIONS=['_main']" -o test.wasm test.c +``` +You will get ```test.wasm``` which is the WASM app binary. + Run WASM app ======================== diff --git a/samples/gui/lvgl-native-ui-app/main.c b/samples/gui/lvgl-native-ui-app/main.c index aeff2f784..54600f332 100644 --- a/samples/gui/lvgl-native-ui-app/main.c +++ b/samples/gui/lvgl-native-ui-app/main.c @@ -96,7 +96,7 @@ int main(int argc, char ** argv) /* Periodically call the lv_task handler. * It could be done in a timer interrupt or an OS task too.*/ if ((count % 100) == 0) { - sprintf(count_str, "%d", count/ 100); + snprintf(count_str, sizeof(count_str), "%d", count/ 100); lv_label_set_text(count_label, count_str); } lv_task_handler(); @@ -146,7 +146,8 @@ static void btn_event_cb(lv_obj_t * btn, lv_event_t event) { if(event == LV_EVENT_RELEASED) { label_count1_value++; - sprintf(label_count1_str, "%d", label_count1_value); + snprintf(label_count1_str, sizeof(label_count1_str), + "%d", label_count1_value); lv_label_set_text(label_count1, label_count1_str); } } diff --git a/samples/gui/wasm-apps/lvgl-compatible/Makefile b/samples/gui/wasm-apps/lvgl-compatible/Makefile index 77dfff72e..99b8e52c1 100644 --- a/samples/gui/wasm-apps/lvgl-compatible/Makefile +++ b/samples/gui/wasm-apps/lvgl-compatible/Makefile @@ -1,7 +1,7 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -CC = emcc +CC = clang-8 APP_DIR = ${shell pwd} IWASM_DIR=../../../../core/iwasm CFLAGS += -O3 \ @@ -23,7 +23,9 @@ SRCS += $(IWASM_DIR)/lib/app-libs/extension/gui/src/*.c all: @$(CC) $(CFLAGS) $(SRCS) \ - -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \ - -s TOTAL_MEMORY=65536 -s TOTAL_STACK=2048\ - -s "EXPORTED_FUNCTIONS=['_on_init', '_on_timer_callback', '_on_widget_event']" \ + --target=wasm32 -O3 -z stack-size=2048 -Wl,--initial-memory=65536 \ + -Wl,--allow-undefined \ + -Wl,--no-threads,--strip-all,--no-entry -nostdlib \ + -Wl,--export=on_init -Wl,--export=on_timer_callback \ + -Wl,--export=on_widget_event \ -o ui_app_lvgl_compatible.wasm diff --git a/samples/gui/wasm-apps/lvgl-compatible/src/main.c b/samples/gui/wasm-apps/lvgl-compatible/src/main.c index bb8fe035c..d5544e612 100644 --- a/samples/gui/wasm-apps/lvgl-compatible/src/main.c +++ b/samples/gui/wasm-apps/lvgl-compatible/src/main.c @@ -24,7 +24,7 @@ char label_count1_str[11] = { 0 }; void timer1_update(user_timer_t timer1) { if ((count % 100) == 0) { - sprintf(count_str, "%d", count / 100); + snprintf(count_str, sizeof(count_str), "%d", count / 100); lv_label_set_text(count_label, count_str); } ++count; @@ -65,7 +65,8 @@ static void btn_event_cb(lv_obj_t *btn, lv_event_t event) { if(event == LV_EVENT_RELEASED) { label_count1_value--; - sprintf(label_count1_str, "%d", label_count1_value); + snprintf(label_count1_str, sizeof(label_count1_str), + "%d", label_count1_value); lv_label_set_text(label_count1, label_count1_str); if (label_count1_value == 0) label_count1_value = 100; diff --git a/samples/gui/wasm-apps/wgl/Makefile b/samples/gui/wasm-apps/wgl/Makefile index 73c9a9f50..e53a83b17 100644 --- a/samples/gui/wasm-apps/wgl/Makefile +++ b/samples/gui/wasm-apps/wgl/Makefile @@ -1,7 +1,7 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -CC = emcc +CC = clang-8 APP_DIR = ${shell pwd} IWASM_DIR=../../../../core/iwasm CFLAGS += -O3 \ @@ -23,7 +23,9 @@ SRCS += $(IWASM_DIR)/lib/app-libs/extension/gui/src/*.c all: @$(CC) $(CFLAGS) $(SRCS) \ - -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \ - -s TOTAL_MEMORY=65536 -s TOTAL_STACK=2048\ - -s "EXPORTED_FUNCTIONS=['_on_init', '_on_timer_callback', '_on_widget_event']" \ + --target=wasm32 -O3 -z stack-size=2048 -Wl,--initial-memory=65536 \ + -Wl,--allow-undefined \ + -Wl,--no-threads,--strip-all,--no-entry -nostdlib \ + -Wl,--export=on_init -Wl,--export=on_timer_callback \ + -Wl,--export=on_widget_event \ -o ui_app.wasm diff --git a/samples/gui/wasm-apps/wgl/src/main.c b/samples/gui/wasm-apps/wgl/src/main.c index feebd060b..758d41648 100644 --- a/samples/gui/wasm-apps/wgl/src/main.c +++ b/samples/gui/wasm-apps/wgl/src/main.c @@ -21,7 +21,7 @@ char label_count1_str[11] = { 0 }; void timer1_update(user_timer_t timer1) { if ((count % 100) == 0) { - sprintf(count_str, "%d", count / 100); + snprintf(count_str, sizeof(count_str), "%d", count / 100); wgl_label_set_text(count_label, count_str); } ++count; @@ -58,7 +58,8 @@ static void btn_event_cb(wgl_obj_t btn, wgl_event_t event) { if(event == WGL_EVENT_RELEASED) { label_count1_value++; - sprintf(label_count1_str, "%d", label_count1_value); + snprintf(label_count1_str, sizeof(label_count1_str), + "%d", label_count1_value); wgl_label_set_text(label_count1, label_count1_str); //wgl_cont_set_fit4(btn, WGL_FIT_FLOOD, WGL_FIT_FLOOD, WGL_FIT_FLOOD, WGL_FIT_FLOOD); diff --git a/samples/gui/wasm-runtime-wgl/linux-build/CMakeLists.txt b/samples/gui/wasm-runtime-wgl/linux-build/CMakeLists.txt index 002b19441..5a66b1690 100644 --- a/samples/gui/wasm-runtime-wgl/linux-build/CMakeLists.txt +++ b/samples/gui/wasm-runtime-wgl/linux-build/CMakeLists.txt @@ -24,7 +24,7 @@ endif () # Set BUILD_TARGET, currently values supported: # "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32" -if (NOT BUILD_TARGET) +if (NOT DEFINED BUILD_TARGET) if (CMAKE_SIZEOF_VOID_P EQUAL 8) # Build as X86_64 by default in 64-bit platform set (BUILD_TARGET "X86_64") diff --git a/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt b/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt index e2fca2cf2..d219b6f69 100644 --- a/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt +++ b/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt @@ -16,10 +16,10 @@ zephyr_compile_definitions (-DNVALGRIND -Dattr_container_free=bh_free -DWASM_ENABLE_GUI=1) -# Build as ARM_32 by default, change to "X86_32", "MIPS_32" or "XTENSA_32" -# if we want to support x86, mips or xtensa -if (NOT BUILD_TARGET) - set (BUILD_TARGET "ARM_32") +# Build as General by default, change to "ARM_32", "X86_32", "MIPS_32" or "XTENSA_32" +# if we want to support arm_32, x86, mips or xtensa +if (NOT DEFINED BUILD_TARGET) + set (BUILD_TARGET "General") endif () string(TOUPPER ${BUILD_TARGET} BUILD_TARGET) @@ -32,108 +32,73 @@ elseif (BUILD_TARGET STREQUAL "MIPS_32") add_definitions(-DBUILD_TARGET_MIPS_32) elseif (BUILD_TARGET STREQUAL "XTENSA_32") add_definitions(-DBUILD_TARGET_XTENSA_32) +elseif (BUILD_TARGET STREQUAL "GENERAL") + # Will use invokeNative_general.c instead of assembly code, + # but the maximum number of native arguments is limited to 20, + # and there are possible issues when passing arguments to + # native function for some cpus, e.g. int64 and double arguments + # in arm and mips need to be 8-bytes aligned, and some arguments + # of x86_64 are passed by registers but not stack else () message (FATAL_ERROR "-- Build target isn't set") endif () message ("-- Build as target ${BUILD_TARGET}") -set (IWASM_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/core/iwasm) -set (APP_MGR_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/core/app-mgr) -set (SHARED_LIB_ROOT ${IWASM_ROOT}/../shared-lib) +set (WASM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/core/iwasm) +set (APP_MGR_DIR ${CMAKE_CURRENT_SOURCE_DIR}/core/app-mgr) +set (SHARED_DIR ${WASM_DIR}/../shared-lib) -target_include_directories(app PRIVATE ${IWASM_ROOT}/runtime/include - ${IWASM_ROOT}/runtime/platform/zephyr - ${IWASM_ROOT}/runtime/platform/include - ${IWASM_ROOT}/runtime/utils - ${IWASM_ROOT}/runtime/vmcore-wasm - ${IWASM_ROOT}/lib/native/base - ${IWASM_ROOT}/lib/native/libc - ${IWASM_ROOT}/lib/native/extension/sensor - ${IWASM_ROOT}/lib/native/extension/connection - ${IWASM_ROOT}/lib/native/extension/gui - ${IWASM_ROOT}/lib/native-interface - ${IWASM_ROOT}/lib/3rdparty - ${IWASM_ROOT}/lib/3rdparty/lvgl - ${IWASM_ROOT}/lib/3rdparty/lvgl/src - ${APP_MGR_ROOT}/app-manager - ${APP_MGR_ROOT}/app-mgr-shared - ${SHARED_LIB_ROOT}/include - ${SHARED_LIB_ROOT}/platform/include - ${SHARED_LIB_ROOT}/platform/zephyr - ${SHARED_LIB_ROOT}/mem-alloc/ems - ${SHARED_LIB_ROOT}/utils - ${SHARED_LIB_ROOT}/coap/er-coap - ${SHARED_LIB_ROOT}/coap/extension - ${CMAKE_CURRENT_SOURCE_DIR}/../src - ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr - ) +set (TARGET_PLATFORM "zephyr") -file (GLOB_RECURSE GUI_SRC ${IWASM_ROOT}/lib/native/extension/gui/*.c ${IWASM_ROOT}/lib/3rdparty/lvgl/*.c) +include (${WASM_DIR}/runtime/platform/${TARGET_PLATFORM}/platform.cmake) +include (${WASM_DIR}/runtime/utils/utils.cmake) +include (${WASM_DIR}/runtime/vmcore-wasm/vmcore.cmake) +include (${WASM_DIR}/lib/native/base/wasm_lib_base.cmake) +include (${WASM_DIR}/lib/native/libc/wasm_libc.cmake) +include (${WASM_DIR}/lib/native/extension/sensor/wasm_lib_sensor.cmake) +include (${WASM_DIR}/lib/native/extension/gui/wasm_lib_gui.cmake) +include (${WASM_DIR}/lib/native/extension/connection/wasm_lib_conn.cmake) +include (${WASM_DIR}/lib/native/extension/connection/${TARGET_PLATFORM}/connection_mgr.cmake) +include (${WASM_DIR}/lib/native-interface/native_interface.cmake) +include (${APP_MGR_DIR}/app-manager/app_mgr.cmake) +include (${APP_MGR_DIR}/app-mgr-shared/app_mgr_shared.cmake) +include (${SHARED_DIR}/platform/${TARGET_PLATFORM}/shared_platform.cmake) +include (${SHARED_DIR}/utils/shared_utils.cmake) +include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) +include (${SHARED_DIR}/coap/lib_coap.cmake) -set (IWASM_SRCS - ${IWASM_ROOT}/runtime/platform/zephyr/wasm_native.c - ${IWASM_ROOT}/runtime/utils/wasm_dlfcn.c - ${IWASM_ROOT}/runtime/utils/wasm_hashmap.c - ${IWASM_ROOT}/runtime/utils/wasm_log.c - ${IWASM_ROOT}/runtime/utils/wasm_vector.c - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_application.c - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_interp.c - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_loader.c - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_runtime.c - ${IWASM_ROOT}/runtime/vmcore-wasm/invokeNative_general.c - ${IWASM_ROOT}/lib/native/base/base_lib_export.c - ${IWASM_ROOT}/lib/native/base/request_response.c - ${IWASM_ROOT}/lib/native/base/timer_wrapper.c - ${IWASM_ROOT}/lib/native/libc/libc_wrapper.c - ${IWASM_ROOT}/lib/native/extension/sensor/runtime_sensor.c - ${IWASM_ROOT}/lib/native/extension/connection/connection_wrapper.c - ${IWASM_ROOT}/lib/native/extension/connection/zephyr/connection_lib_impl.c - ${GUI_SRC} - ${IWASM_ROOT}/lib/native-interface/attr_container.c - ${IWASM_ROOT}/lib/native-interface/restful_utils.c - ${APP_MGR_ROOT}/app-manager/app_manager.c - ${APP_MGR_ROOT}/app-manager/app_manager_host.c - ${APP_MGR_ROOT}/app-manager/ble_msg.c - ${APP_MGR_ROOT}/app-manager/event.c - ${APP_MGR_ROOT}/app-manager/message.c - ${APP_MGR_ROOT}/app-manager/module_jeff.c - ${APP_MGR_ROOT}/app-manager/module_utils.c - ${APP_MGR_ROOT}/app-manager/module_wasm_app.c - ${APP_MGR_ROOT}/app-manager/module_wasm_lib.c - ${APP_MGR_ROOT}/app-manager/resource_reg.c - ${APP_MGR_ROOT}/app-manager/watchdog.c - ${APP_MGR_ROOT}/app-manager/platform/zephyr/app_mgr_zephyr.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_assert.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_definition.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_platform.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_platform_log.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_thread.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_time.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_math.c - ${SHARED_LIB_ROOT}/mem-alloc/bh_memory.c - ${SHARED_LIB_ROOT}/mem-alloc/mem_alloc.c - ${SHARED_LIB_ROOT}/mem-alloc/ems/ems_alloc.c - ${SHARED_LIB_ROOT}/mem-alloc/ems/ems_hmu.c - ${SHARED_LIB_ROOT}/mem-alloc/ems/ems_kfc.c - ${SHARED_LIB_ROOT}/mem-alloc/tlsf/tlsf.c - ${SHARED_LIB_ROOT}/utils/bh_list.c - ${SHARED_LIB_ROOT}/utils/bh_log.c - ${SHARED_LIB_ROOT}/utils/bh_queue.c - ${SHARED_LIB_ROOT}/utils/runtime_timer.c - ${SHARED_LIB_ROOT}/coap/er-coap/er-coap.c - ${SHARED_LIB_ROOT}/coap/extension/coap_conversion.c - ${SHARED_LIB_ROOT}/coap/extension/coap_over_tcp.c - ) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr) - set (LVGL_DRV_SRCS +set (LVGL_DRV_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/display_ili9340_adafruit_1480.c ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/display_ili9340.c ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/XPT2046.c ) -target_sources(app PRIVATE ${IWASM_SRCS} - ${LVGL_DRV_SRCS} - ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/iwasm_main.c - ${CMAKE_CURRENT_SOURCE_DIR}/../src/ext_lib_export.c) +set (IWASM_SRCS + ${WASM_PLATFORM_LIB_SOURCE} + ${WASM_UTILS_LIB_SOURCE} + ${VMCORE_LIB_SOURCE} + ${WASM_LIBC_SOURCE} + ${APP_MGR_SOURCE} + ${WASM_LIB_BASE_SOURCE} + ${WASM_LIB_EXT_SOURCE} + ${WASM_LIB_SENSOR_SOURCE} + ${WASM_LIB_GUI_SOURCE} + ${WASM_LIB_CONN_SOURCE} + ${WASM_LIB_CONN_MGR_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ) + +target_sources(app PRIVATE + ${IWASM_SRCS} + ${LVGL_DRV_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/iwasm_main.c + ${CMAKE_CURRENT_SOURCE_DIR}/../src/ext_lib_export.c + ) diff --git a/samples/littlevgl/vgl-native-ui-app/main.c b/samples/littlevgl/vgl-native-ui-app/main.c index ef26e5e37..4d403c2ba 100644 --- a/samples/littlevgl/vgl-native-ui-app/main.c +++ b/samples/littlevgl/vgl-native-ui-app/main.c @@ -55,7 +55,8 @@ char label_count1_str[11] = { 0 }; static lv_res_t btn_rel_action(lv_obj_t * btn) { label_count1_value++; - sprintf(label_count1_str, "%d", label_count1_value); + snprintf(label_count1_str, sizeof(label_count1_str), + "%d", label_count1_value); lv_label_set_text(label_count1, label_count1_str); return LV_RES_OK; } @@ -95,7 +96,7 @@ int main() /* Periodically call the lv_task handler. * It could be done in a timer interrupt or an OS task too.*/ if ((count % 100) == 0) { - sprintf(count_str, "%d", count/ 100); + snprintf(count_str, sizeof(count_str), "%d", count/ 100); lv_label_set_text(count_label, count_str); } lv_task_handler(); diff --git a/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt b/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt index 7518688fd..a853e7a4e 100644 --- a/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt +++ b/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt @@ -14,7 +14,7 @@ endif () # Set BUILD_TARGET, currently values supported: # "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32" -if (NOT BUILD_TARGET) +if (NOT DEFINED BUILD_TARGET) if (CMAKE_SIZEOF_VOID_P EQUAL 8) # Build as X86_64 by default in 64-bit platform set (BUILD_TARGET "X86_64") diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/display_indev.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/display_indev.c index b9334fbf9..c11867f14 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/display_indev.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/display_indev.c @@ -22,8 +22,6 @@ void monitor_sdl_clean_up(void); static uint32_t tft_fb[MONITOR_HOR_RES * MONITOR_VER_RES]; - - int time_get_ms(wasm_module_inst_t module_inst) { @@ -42,7 +40,7 @@ static volatile bool sdl_refr_qry = false; static volatile bool sdl_quit_qry = false; void monitor_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, - const lv_color_t * color_p) + const lv_color_t * color_p) { /*Return if the area is out the screen*/ if (x2 < 0 || y2 < 0 || x1 > MONITOR_HOR_RES - 1 @@ -52,16 +50,16 @@ void monitor_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t y; uint32_t w = x2 - x1 + 1; + for (y = y1; y <= y2; y++) { memcpy(&tft_fb[y * MONITOR_HOR_RES + x1], color_p, - w * sizeof(lv_color_t)); + w * sizeof(lv_color_t)); color_p += w; } sdl_refr_qry = true; /*IMPORTANT! It must be called to tell the system the flush is ready*/ - } /** @@ -73,7 +71,7 @@ void monitor_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, * @param color fill color */ void monitor_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, - lv_color_t color) + lv_color_t color) { /*Return if the area is out the screen*/ if (x2 < 0) @@ -113,7 +111,7 @@ void monitor_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, * @param color_p an array of colors */ void monitor_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, - const lv_color_t * color_p) + const lv_color_t * color_p) { /*Return if the area is out the screen*/ if (x2 < 0) diff --git a/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt index 511048d62..400cce6b5 100644 --- a/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt +++ b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt @@ -15,10 +15,10 @@ zephyr_compile_definitions (-DNVALGRIND -Dattr_container_malloc=bh_malloc -Dattr_container_free=bh_free) -# Build as ARM_32 by default, change to "X86_32", "MIPS_32" or "XTENSA_32" -# if we want to support x86, mips or xtensa -if (NOT BUILD_TARGET) - set (BUILD_TARGET "ARM_32") +# Build as General by default, change to "ARM_32", "X86_32", "MIPS_32" or "XTENSA_32" +# if we want to support arm_32, x86, mips or xtensa +if (NOT DEFINED BUILD_TARGET) + set (BUILD_TARGET "General") endif () string(TOUPPER ${BUILD_TARGET} BUILD_TARGET) @@ -31,101 +31,70 @@ elseif (BUILD_TARGET STREQUAL "MIPS_32") add_definitions(-DBUILD_TARGET_MIPS_32) elseif (BUILD_TARGET STREQUAL "XTENSA_32") add_definitions(-DBUILD_TARGET_XTENSA_32) +elseif (BUILD_TARGET STREQUAL "GENERAL") + # Will use invokeNative_general.c instead of assembly code, + # but the maximum number of native arguments is limited to 20, + # and there are possible issues when passing arguments to + # native function for some cpus, e.g. int64 and double arguments + # in arm and mips need to be 8-bytes aligned, and some arguments + # of x86_64 are passed by registers but not stack else () message (FATAL_ERROR "-- Build target isn't set") endif () message ("-- Build as target ${BUILD_TARGET}") -set (IWASM_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/core/iwasm) -set (APP_MGR_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/core/app-mgr) -set (SHARED_LIB_ROOT ${IWASM_ROOT}/../shared-lib) +set (WASM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/core/iwasm) +set (APP_MGR_DIR ${CMAKE_CURRENT_SOURCE_DIR}/core/app-mgr) +set (SHARED_DIR ${WASM_DIR}/../shared-lib) -target_include_directories(app PRIVATE ${IWASM_ROOT}/runtime/include - ${IWASM_ROOT}/runtime/platform/zephyr - ${IWASM_ROOT}/runtime/platform/include - ${IWASM_ROOT}/runtime/utils - ${IWASM_ROOT}/runtime/vmcore-wasm - ${IWASM_ROOT}/lib/native/base - ${IWASM_ROOT}/lib/native/libc - ${IWASM_ROOT}/lib/native/extension/sensor - ${IWASM_ROOT}/lib/native/extension/connection - ${IWASM_ROOT}/lib/native-interface - ${APP_MGR_ROOT}/app-manager - ${APP_MGR_ROOT}/app-mgr-shared - ${SHARED_LIB_ROOT}/include - ${SHARED_LIB_ROOT}/platform/include - ${SHARED_LIB_ROOT}/platform/zephyr - ${SHARED_LIB_ROOT}/mem-alloc/ems - ${SHARED_LIB_ROOT}/utils - ${SHARED_LIB_ROOT}/coap/er-coap - ${SHARED_LIB_ROOT}/coap/extension - ${CMAKE_CURRENT_SOURCE_DIR}/../src - ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr - ) +set (TARGET_PLATFORM "zephyr") -set (IWASM_SRCS - ${IWASM_ROOT}/runtime/platform/zephyr/wasm_native.c - ${IWASM_ROOT}/runtime/utils/wasm_dlfcn.c - ${IWASM_ROOT}/runtime/utils/wasm_hashmap.c - ${IWASM_ROOT}/runtime/utils/wasm_log.c - ${IWASM_ROOT}/runtime/utils/wasm_vector.c - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_application.c - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_interp.c - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_loader.c - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_runtime.c - ${IWASM_ROOT}/runtime/vmcore-wasm/invokeNative_general.c - ${IWASM_ROOT}/lib/native/base/base_lib_export.c - ${IWASM_ROOT}/lib/native/base/request_response.c - ${IWASM_ROOT}/lib/native/base/timer_wrapper.c - ${IWASM_ROOT}/lib/native/libc/libc_wrapper.c - ${IWASM_ROOT}/lib/native/extension/sensor/runtime_sensor.c - ${IWASM_ROOT}/lib/native/extension/connection/connection_wrapper.c - ${IWASM_ROOT}/lib/native/extension/connection/zephyr/connection_lib_impl.c - ${IWASM_ROOT}/lib/native-interface/attr_container.c - ${IWASM_ROOT}/lib/native-interface/restful_utils.c - ${APP_MGR_ROOT}/app-manager/app_manager.c - ${APP_MGR_ROOT}/app-manager/app_manager_host.c - ${APP_MGR_ROOT}/app-manager/ble_msg.c - ${APP_MGR_ROOT}/app-manager/event.c - ${APP_MGR_ROOT}/app-manager/message.c - ${APP_MGR_ROOT}/app-manager/module_jeff.c - ${APP_MGR_ROOT}/app-manager/module_utils.c - ${APP_MGR_ROOT}/app-manager/module_wasm_app.c - ${APP_MGR_ROOT}/app-manager/module_wasm_lib.c - ${APP_MGR_ROOT}/app-manager/resource_reg.c - ${APP_MGR_ROOT}/app-manager/watchdog.c - ${APP_MGR_ROOT}/app-manager/platform/zephyr/app_mgr_zephyr.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_assert.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_definition.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_platform.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_platform_log.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_thread.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_time.c - ${SHARED_LIB_ROOT}/platform/zephyr/bh_math.c - ${SHARED_LIB_ROOT}/mem-alloc/bh_memory.c - ${SHARED_LIB_ROOT}/mem-alloc/mem_alloc.c - ${SHARED_LIB_ROOT}/mem-alloc/ems/ems_alloc.c - ${SHARED_LIB_ROOT}/mem-alloc/ems/ems_hmu.c - ${SHARED_LIB_ROOT}/mem-alloc/ems/ems_kfc.c - ${SHARED_LIB_ROOT}/mem-alloc/tlsf/tlsf.c - ${SHARED_LIB_ROOT}/utils/bh_list.c - ${SHARED_LIB_ROOT}/utils/bh_log.c - ${SHARED_LIB_ROOT}/utils/bh_queue.c - ${SHARED_LIB_ROOT}/utils/runtime_timer.c - ${SHARED_LIB_ROOT}/coap/er-coap/er-coap.c - ${SHARED_LIB_ROOT}/coap/extension/coap_conversion.c - ${SHARED_LIB_ROOT}/coap/extension/coap_over_tcp.c - ) +include (${WASM_DIR}/runtime/platform/${TARGET_PLATFORM}/platform.cmake) +include (${WASM_DIR}/runtime/utils/utils.cmake) +include (${WASM_DIR}/runtime/vmcore-wasm/vmcore.cmake) +include (${WASM_DIR}/lib/native/base/wasm_lib_base.cmake) +include (${WASM_DIR}/lib/native/libc/wasm_libc.cmake) +include (${WASM_DIR}/lib/native/extension/sensor/wasm_lib_sensor.cmake) +include (${WASM_DIR}/lib/native/extension/connection/wasm_lib_conn.cmake) +include (${WASM_DIR}/lib/native/extension/connection/${TARGET_PLATFORM}/connection_mgr.cmake) +include (${WASM_DIR}/lib/native-interface/native_interface.cmake) +include (${APP_MGR_DIR}/app-manager/app_mgr.cmake) +include (${APP_MGR_DIR}/app-mgr-shared/app_mgr_shared.cmake) +include (${SHARED_DIR}/platform/${TARGET_PLATFORM}/shared_platform.cmake) +include (${SHARED_DIR}/utils/shared_utils.cmake) +include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) +include (${SHARED_DIR}/coap/lib_coap.cmake) - set (LVGL_DRV_SRCS +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr) + +set (LVGL_DRV_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/display_ili9340_adafruit_1480.c ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/display_ili9340.c ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/display_indev.c ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/XPT2046.c ) -target_sources(app PRIVATE ${IWASM_SRCS} - ${LVGL_DRV_SRCS} - ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/main.c - ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/iwasm_main.c - ${CMAKE_CURRENT_SOURCE_DIR}/../src/ext_lib_export.c) +set (IWASM_SRCS + ${WASM_PLATFORM_LIB_SOURCE} + ${WASM_UTILS_LIB_SOURCE} + ${VMCORE_LIB_SOURCE} + ${WASM_LIBC_SOURCE} + ${APP_MGR_SOURCE} + ${WASM_LIB_BASE_SOURCE} + ${WASM_LIB_EXT_SOURCE} + ${WASM_LIB_SENSOR_SOURCE} + ${WASM_LIB_CONN_SOURCE} + ${WASM_LIB_CONN_MGR_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ) +target_sources(app PRIVATE + ${IWASM_SRCS} + ${LVGL_DRV_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/iwasm_main.c + ${CMAKE_CURRENT_SOURCE_DIR}/../src/ext_lib_export.c + ) diff --git a/samples/littlevgl/wasm-apps/Makefile_wasm_app b/samples/littlevgl/wasm-apps/Makefile_wasm_app index 97046d914..d737eb7f0 100644 --- a/samples/littlevgl/wasm-apps/Makefile_wasm_app +++ b/samples/littlevgl/wasm-apps/Makefile_wasm_app @@ -1,7 +1,7 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -CC = emcc +CC = clang-8 LVGL_DIR = ${shell pwd} IWASM_DIR=../../../core/iwasm CFLAGS += -O3 \ @@ -50,7 +50,8 @@ SRCS += $(LVGL_DIR)/src/main.c SRCS += $(IWASM_DIR)/lib/app-libs/base/timer.c all: @$(CC) $(CFLAGS) $(SRCS) \ - -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \ - -s TOTAL_MEMORY=65536 -s TOTAL_STACK=2048\ - -s "EXPORTED_FUNCTIONS=['_on_init', '_on_timer_callback']" \ + --target=wasm32 -O3 -z stack-size=2048 -Wl,--initial-memory=65536 \ + -Wl,--allow-undefined \ + -Wl,--no-threads,--strip-all,--no-entry -nostdlib \ + -Wl,--export=on_init -Wl,--export=on_timer_callback \ -o ui_app.wasm diff --git a/samples/littlevgl/wasm-apps/src/main.c b/samples/littlevgl/wasm-apps/src/main.c index c5187d3f6..07dcaa9d7 100644 --- a/samples/littlevgl/wasm-apps/src/main.c +++ b/samples/littlevgl/wasm-apps/src/main.c @@ -56,7 +56,7 @@ char label_count1_str[11] = { 0 }; void timer1_update(user_timer_t timer1) { if ((count % 100) == 0) { - sprintf(count_str, "%d", count / 100); + snprintf(count_str, sizeof(count_str), "%d", count / 100); lv_label_set_text(count_label, count_str); } lv_task_handler(); @@ -67,7 +67,8 @@ void timer1_update(user_timer_t timer1) static lv_res_t btn_rel_action(lv_obj_t * btn) { label_count1_value++; - sprintf(label_count1_str, "%d", label_count1_value); + snprintf(label_count1_str, sizeof(label_count1_str), + "%d", label_count1_value); lv_label_set_text(label_count1, label_count1_str); return LV_RES_OK; } diff --git a/samples/simple/CMakeLists.txt b/samples/simple/CMakeLists.txt index 698433493..07be7bd60 100644 --- a/samples/simple/CMakeLists.txt +++ b/samples/simple/CMakeLists.txt @@ -16,7 +16,7 @@ set (BUILD_AS_64BIT_SUPPORT "YES") # Set BUILD_TARGET, currently values supported: # "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32" -if (NOT BUILD_TARGET) +if (NOT DEFINED BUILD_TARGET) if (CMAKE_SIZEOF_VOID_P EQUAL 8) if (BUILD_AS_64BIT_SUPPORT STREQUAL "YES") # Build as X86_64 by default in 64-bit platform diff --git a/samples/simple/build.sh b/samples/simple/build.sh index 5289098f4..03a76d645 100755 --- a/samples/simple/build.sh +++ b/samples/simple/build.sh @@ -63,15 +63,18 @@ for i in `ls *.c` do APP_SRC="$i ${APP_LIB_SRC}" OUT_FILE=${i%.*}.wasm -emcc -O3 -I${APP_LIBS}/base -I${APP_LIBS}/extension/sensor -I${NATIVE_LIBS} \ - -I${APP_LIBS}/extension/connection \ - -I${APP_LIBS}/extension/gui \ - -DENABLE_WGL=1 \ - -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \ - -s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 \ - -s "EXPORTED_FUNCTIONS=['_on_init', '_on_destroy', '_on_request', '_on_response', \ - '_on_sensor_event', '_on_timer_callback', '_on_connection_data', '_on_widget_event']" \ - -o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC} +clang-8 -I${APP_LIBS}/base -I${APP_LIBS}/extension/sensor -I${NATIVE_LIBS} \ + -I${APP_LIBS}/extension/connection \ + -I${APP_LIBS}/extension/gui \ + -DENABLE_WGL=1 \ + --target=wasm32 -O3 -z stack-size=4096 -Wl,--initial-memory=65536 \ + -Wl,--allow-undefined \ + -Wl,--no-threads,--strip-all,--no-entry -nostdlib \ + -Wl,--export=on_init -Wl,--export=on_destroy \ + -Wl,--export=on_request -Wl,--export=on_response \ + -Wl,--export=on_sensor_event -Wl,--export=on_timer_callback \ + -Wl,--export=on_connection_data -Wl,--export=on_widget_event \ + -o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC} if [ -f ${OUT_DIR}/wasm-apps/${OUT_FILE} ]; then echo "build ${OUT_FILE} success" else diff --git a/samples/simple/build_no_gui.sh b/samples/simple/build_no_gui.sh index 0e959e4e1..01e958570 100755 --- a/samples/simple/build_no_gui.sh +++ b/samples/simple/build_no_gui.sh @@ -55,13 +55,16 @@ for i in `ls *.c | grep -v gui` do APP_SRC="$i ${APP_LIB_SRC}" OUT_FILE=${i%.*}.wasm -emcc -O3 -I${APP_LIBS}/base -I${APP_LIBS}/extension/sensor -I${NATIVE_LIBS} \ - -I${APP_LIBS}/extension/connection \ - -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \ - -s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 \ - -s "EXPORTED_FUNCTIONS=['_on_init', '_on_destroy', '_on_request', '_on_response', \ - '_on_sensor_event', '_on_timer_callback', '_on_connection_data']" \ - -o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC} +clang-8 -I${APP_LIBS}/base -I${APP_LIBS}/extension/sensor -I${NATIVE_LIBS} \ + -I${APP_LIBS}/extension/connection \ + --target=wasm32 -O3 -z stack-size=4096 -Wl,--initial-memory=65536 \ + -Wl,--allow-undefined \ + -Wl,--no-threads,--strip-all,--no-entry -nostdlib \ + -Wl,--export=on_init -Wl,--export=on_destroy \ + -Wl,--export=on_request -Wl,--export=on_response \ + -Wl,--export=on_sensor_event -Wl,--export=on_timer_callback \ + -Wl,--export=on_connection_data \ + -o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC} if [ -f ${OUT_DIR}/wasm-apps/${OUT_FILE} ]; then echo "build ${OUT_FILE} success" else diff --git a/samples/simple/src/main.c b/samples/simple/src/main.c index 14afb0780..5bf24ce67 100644 --- a/samples/simple/src/main.c +++ b/samples/simple/src/main.c @@ -2,4 +2,5 @@ extern void iwasm_main(); int main(int argc, char *argv[]) { iwasm_main(argc, argv); + return 0; } diff --git a/samples/simple/wasm-apps/gui.c b/samples/simple/wasm-apps/gui.c index 0ab1a7be5..1460ff700 100644 --- a/samples/simple/wasm-apps/gui.c +++ b/samples/simple/wasm-apps/gui.c @@ -22,7 +22,7 @@ char label_count1_str[11] = { 0 }; void timer1_update(user_timer_t timer1) { if ((count % 100) == 0) { - sprintf(count_str, "%d", count / 100); + snprintf(count_str, sizeof(count_str), "%d", count / 100); wgl_label_set_text(count_label, count_str); } ++count; @@ -63,7 +63,8 @@ static void btn_event_cb(wgl_obj_t btn, wgl_event_t event) { if(event == WGL_EVENT_RELEASED) { label_count1_value++; - sprintf(label_count1_str, "%d", label_count1_value); + snprintf(label_count1_str, sizeof(label_count1_str), + "%d", label_count1_value); wgl_label_set_text(label_count1, label_count1_str); } } diff --git a/samples/simple/wasm-apps/gui_lvgl_compatible.c b/samples/simple/wasm-apps/gui_lvgl_compatible.c index bb8fe035c..d5544e612 100644 --- a/samples/simple/wasm-apps/gui_lvgl_compatible.c +++ b/samples/simple/wasm-apps/gui_lvgl_compatible.c @@ -24,7 +24,7 @@ char label_count1_str[11] = { 0 }; void timer1_update(user_timer_t timer1) { if ((count % 100) == 0) { - sprintf(count_str, "%d", count / 100); + snprintf(count_str, sizeof(count_str), "%d", count / 100); lv_label_set_text(count_label, count_str); } ++count; @@ -65,7 +65,8 @@ static void btn_event_cb(lv_obj_t *btn, lv_event_t event) { if(event == LV_EVENT_RELEASED) { label_count1_value--; - sprintf(label_count1_str, "%d", label_count1_value); + snprintf(label_count1_str, sizeof(label_count1_str), + "%d", label_count1_value); lv_label_set_text(label_count1, label_count1_str); if (label_count1_value == 0) label_count1_value = 100; diff --git a/test-tools/host-tool/external/cJSON/cJSON.c b/test-tools/host-tool/external/cJSON/cJSON.c index 2776ce671..b948d6d75 100644 --- a/test-tools/host-tool/external/cJSON/cJSON.c +++ b/test-tools/host-tool/external/cJSON/cJSON.c @@ -88,7 +88,8 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) { CJSON_PUBLIC(const char*) cJSON_Version(void) { static char version[15]; - sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + snprintf(version, sizeof(version), "%i.%i.%i", + CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); return version; } @@ -446,20 +447,20 @@ static cJSON_bool print_number(const cJSON * const item, /* This checks for NaN and Infinity */ if ((d * 0) != 0) { - length = sprintf((char*) number_buffer, "null"); + length = snprintf((char*) number_buffer, sizeof(number_buffer), "null"); } else { /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ - length = sprintf((char*) number_buffer, "%1.15g", d); + length = snprintf((char*) number_buffer, sizeof(number_buffer), "%1.15g", d); /* Check whether the original double can be recovered */ if ((sscanf((char*) number_buffer, "%lg", &test) != 1) || ((double) test != d)) { /* If not, print with 17 decimal places of precision */ - length = sprintf((char*) number_buffer, "%1.17g", d); + length = snprintf((char*) number_buffer, sizeof(number_buffer), "%1.17g", d); } } - /* sprintf failed or buffer overrun occured */ + /* snprintf failed or buffer overrun occured */ if ((length < 0) || (length > (int) (sizeof(number_buffer) - 1))) { return false; } @@ -748,7 +749,7 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) { const unsigned char *input_pointer = NULL; - unsigned char *output = NULL; + unsigned char *output = NULL, *output_end; unsigned char *output_pointer = NULL; size_t output_length = 0; /* numbers of additional characters needed for escaping */ @@ -796,6 +797,7 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, if (output == NULL) { return false; } + output_end = output + output_length + sizeof("\"\""); /* no characters have to be escaped */ if (escape_characters == 0) { @@ -843,7 +845,8 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, break; default: /* escape and print as unicode codepoint */ - sprintf((char*) output_pointer, "u%04x", *input_pointer); + snprintf((char*) output_pointer, output_end - output_pointer, + "u%04x", *input_pointer); output_pointer += 4; break; } diff --git a/test-tools/host-tool/src/main.c b/test-tools/host-tool/src/main.c index f30fb1e28..c4aeb0cbf 100644 --- a/test-tools/host-tool/src/main.c +++ b/test-tools/host-tool/src/main.c @@ -298,7 +298,7 @@ static int subscribe(reg_info *info) p = strtok(info->urls, ","); while(p != NULL) { char url[URL_MAX_LEN] = {0}; - sprintf(url, "%s%s", "/event/", p); + snprintf(url, URL_MAX_LEN, "%s%s", "/event/", p); init_request(request, url, COAP_PUT, @@ -312,7 +312,7 @@ static int subscribe(reg_info *info) #else char url[URL_MAX_LEN] = { 0 }; char *prefix = info->urls[0] == '/' ? "/event" : "/event/"; - sprintf(url, "%s%s", prefix, info->urls); + snprintf(url, URL_MAX_LEN, "%s%s", prefix, info->urls); init_request(request, url, COAP_PUT, FMT_ATTR_CONTAINER, NULL, 0); @@ -332,7 +332,7 @@ static int unsubscribe(unreg_info *info) p = strtok(info->urls, ","); while(p != NULL) { char url[URL_MAX_LEN] = {0}; - sprintf(url, "%s%s", "/event/", p); + snprintf(url, URL_MAX_LEN, "%s%s", "/event/", p); init_request(request, url, COAP_DELETE, @@ -345,7 +345,7 @@ static int unsubscribe(unreg_info *info) } #else char url[URL_MAX_LEN] = { 0 }; - sprintf(url, "%s%s", "/event/", info->urls); + snprintf(url, URL_MAX_LEN, "%s%s", "/event/", info->urls); init_request(request, url, COAP_DELETE, FMT_ATTR_CONTAINER, NULL, 0); @@ -777,7 +777,7 @@ int main(int argc, char *argv[]) int ret; imrt_link_recv_context_t recv_ctx = { 0 }; char buffer[BUF_SIZE] = { 0 }; - uint32_t last_check, total_elpased_ms = 0; + uint32_t last_check = 0, total_elpased_ms = 0; bool is_responsed = false; operation op; diff --git a/test-tools/toolchain/sysroot/include/ctype.h b/test-tools/toolchain/sysroot/include/ctype.h index 20a71dc72..1a3cd4e54 100644 --- a/test-tools/toolchain/sysroot/include/ctype.h +++ b/test-tools/toolchain/sysroot/include/ctype.h @@ -10,8 +10,16 @@ extern "C" { #endif - - +int isupper(int c); +int isalpha(int c); +int isspace(int c); +int isgraph(int c); +int isprint(int c); +int isdigit(int c); +int isxdigit(int c); +int tolower(int c); +int toupper(int c); +int isalnum(int c); #ifdef __cplusplus } diff --git a/test-tools/toolchain/sysroot/include/limits.h b/test-tools/toolchain/sysroot/include/limits.h index ba1538870..d46fb4fcb 100644 --- a/test-tools/toolchain/sysroot/include/limits.h +++ b/test-tools/toolchain/sysroot/include/limits.h @@ -10,8 +10,22 @@ extern "C" { #endif - - +#define CHAR_BIT 8 +#define SCHAR_MIN -128 +#define SCHAR_MAX 127 +#define UCHAR_MAX 255 +#define CHAR_MIN 0 +#define CHAR_MAX 127 +#define MB_LEN_MAX 1 +#define SHRT_MIN -32768 +#define SHRT_MAX +32767 +#define USHRT_MAX 65535 +#define INT_MIN -32768 +#define INT_MAX +32767 +#define UINT_MAX 65535 +#define LONG_MIN -2147483648 +#define LONG_MAX +2147483647 +#define ULONG_MAX 4294967295 #ifdef __cplusplus } diff --git a/test-tools/toolchain/sysroot/include/stdio.h b/test-tools/toolchain/sysroot/include/stdio.h index d7350f338..986d16f5b 100644 --- a/test-tools/toolchain/sysroot/include/stdio.h +++ b/test-tools/toolchain/sysroot/include/stdio.h @@ -10,6 +10,10 @@ extern "C" { #endif +#ifndef NULL +# define NULL ((void*) 0) +#endif + typedef unsigned int size_t; int printf(const char *format, ...); diff --git a/test-tools/toolchain/sysroot/include/stdlib.h b/test-tools/toolchain/sysroot/include/stdlib.h index 8fdd17c2b..14ab7c1f7 100644 --- a/test-tools/toolchain/sysroot/include/stdlib.h +++ b/test-tools/toolchain/sysroot/include/stdlib.h @@ -12,6 +12,10 @@ extern "C" { typedef unsigned int size_t; +int atoi(const char *s); +void exit(int status); +long strtol(const char *nptr, char **endptr, register int base); +unsigned long strtoul(const char *nptr, char **endptr, register int base) void *malloc(size_t size); void *calloc(size_t n, size_t size); void free(void *ptr); diff --git a/test-tools/toolchain/sysroot/include/string.h b/test-tools/toolchain/sysroot/include/string.h index c5d17e8d2..541ba8ffe 100644 --- a/test-tools/toolchain/sysroot/include/string.h +++ b/test-tools/toolchain/sysroot/include/string.h @@ -16,6 +16,11 @@ int memcmp(const void *s1, const void *s2, size_t n); void *memcpy(void *dest, const void *src, size_t n); void *memmove(void *dest, const void *src, size_t n); void *memset(void *s, int c, size_t n); +void *memchr(const void *s, int c, size_t n); +int strncasecmp(const char *s1, const char *s2, size_t n); +size_t strspn(const char *s, const char *accept); +size_t strcspn(const char *s, const char *reject); +char *strstr(const char *s, const char *find); char *strchr(const char *s, int c); int strcmp(const char *s1, const char *s2); char *strcpy(char *dest, const char *src); diff --git a/test-tools/toolchain/sysroot/include/time.h b/test-tools/toolchain/sysroot/include/time.h deleted file mode 100644 index 5da37a581..000000000 --- a/test-tools/toolchain/sysroot/include/time.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _WAMR_LIBC_TIME_H -#define _WAMR_LIBC_TIME_H - -#ifdef __cplusplus -extern "C" { -#endif - - - - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/test-tools/toolchain/sysroot/share/defined-symbols.txt b/test-tools/toolchain/sysroot/share/defined-symbols.txt index a10eac143..544d7ef4a 100644 --- a/test-tools/toolchain/sysroot/share/defined-symbols.txt +++ b/test-tools/toolchain/sysroot/share/defined-symbols.txt @@ -47,10 +47,30 @@ malloc calloc strdup free +atoi +bsearch +exit +strtol +strtoul +memchr +strncasecmp +strspn +strcspn +strstr +isupper +isalpha +isspace +isgraph +isprint +isdigit +isxdigit +tolower +toupper +isalnum llvm_bswap_i16 llvm_bswap_i32 bitshift64Lshr bitshift64Shl llvm_stackrestore llvm_stacksave -emscripten_memcpy_big \ No newline at end of file +emscripten_memcpy_big