diff options
author | Ben Murdoch <benm@google.com> | 2014-04-10 11:22:14 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2014-04-10 11:22:14 +0100 |
commit | c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c (patch) | |
tree | e9edd581ad60ab80aa5ab423a2a80df652a75792 /native_client_sdk | |
parent | 54cd42278ccf1d52996034848086a09b23065a40 (diff) | |
download | chromium_org-c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c.tar.gz |
Merge from Chromium at DEPS revision 262940
This commit was generated by merge_to_master.py.
Change-Id: I9a3fddbb29857fa8f68a18c6a0115862b65f84d1
Diffstat (limited to 'native_client_sdk')
63 files changed, 1205 insertions, 245 deletions
diff --git a/native_client_sdk/src/build_tools/build_projects.py b/native_client_sdk/src/build_tools/build_projects.py index 11cc455ebf..dd8ec1c2cc 100755 --- a/native_client_sdk/src/build_tools/build_projects.py +++ b/native_client_sdk/src/build_tools/build_projects.py @@ -185,6 +185,10 @@ def BuildProjectsBranch(pepperdir, branch, deps, clean, config, args=None): make_cmd = [make, '-j', jobs] make_cmd.append('CONFIG='+config) + # We always ENABLE_BIONIC in case we need it. If neither --bionic nor + # -t bionic have been provided on the command line, then VALID_TOOLCHAINS + # will not contain a bionic target. + make_cmd.append('ENABLE_BIONIC=1') if not deps: make_cmd.append('IGNORE_DEPS=1') @@ -224,6 +228,8 @@ def main(argv): parser.add_option('--config', help='Choose configuration to build (Debug or Release). Builds both ' 'by default') + parser.add_option('--bionic', + help='Enable bionic projects', action='store_true') parser.add_option('-x', '--experimental', help='Build experimental projects', action='store_true') parser.add_option('-t', '--toolchain', @@ -259,7 +265,7 @@ def main(argv): # e.g. If an example supports newlib and glibc, then the default will be # newlib. options.toolchain = ['pnacl', 'newlib', 'glibc', 'host'] - if options.experimental: + if options.experimental or options.bionic: options.toolchain.append('bionic') if 'host' in options.toolchain: diff --git a/native_client_sdk/src/build_tools/build_sdk.py b/native_client_sdk/src/build_tools/build_sdk.py index 790f062225..7746c7a4f8 100755 --- a/native_client_sdk/src/build_tools/build_sdk.py +++ b/native_client_sdk/src/build_tools/build_sdk.py @@ -294,7 +294,7 @@ NACL_HEADER_MAP = { ('native_client/src/untrusted/pthread/pthread.h', ''), ('native_client/src/untrusted/pthread/semaphore.h', ''), ('native_client/src/untrusted/valgrind/dynamic_annotations.h', 'nacl/'), - ('ppapi/nacl_irt/irt_ppapi.h', ''), + ('ppapi/nacl_irt/public/irt_ppapi.h', ''), ], 'glibc': [ ('native_client/src/include/nacl/nacl_exception.h', 'nacl/'), @@ -305,7 +305,7 @@ NACL_HEADER_MAP = { ('native_client/src/untrusted/nacl/nacl_startup.h', 'nacl/'), ('native_client/src/untrusted/nacl/nacl_thread.h', 'nacl/'), ('native_client/src/untrusted/valgrind/dynamic_annotations.h', 'nacl/'), - ('ppapi/nacl_irt/irt_ppapi.h', ''), + ('ppapi/nacl_irt/public/irt_ppapi.h', ''), ], 'host': [] } @@ -368,6 +368,15 @@ def MakeNinjaRelPath(path): TOOLCHAIN_LIBS = { + 'bionic' : [ + 'libminidump_generator.a', + 'libnacl.a', + 'libnacl_dyncode.a', + 'libnacl_exception.a', + 'libnacl_list_mappings.a', + 'libppapi.a', + 'libppapi_stub.a', + ], 'newlib' : [ 'crti.o', 'crtn.o', @@ -448,6 +457,17 @@ def GypNinjaInstall(pepperdir, toolchains): InstallFiles(ninja_out_dir, os.path.join(pepperdir, 'tools'), tools_files) + # Add ARM binaries + if platform == 'linux': + tools_files = [ + ['irt_core_newlib_arm.nexe', 'irt_core_arm.nexe'], + ['irt_core_newlib_arm.nexe', 'irt_core_arm.nexe'], + ['sel_ldr', 'sel_ldr_arm'], + ['nacl_helper_bootstrap', 'nacl_helper_bootstrap_arm'] + ] + ninja_out_dir = os.path.join(OUT_DIR, build_dir + '-arm', 'Release') + InstallFiles(ninja_out_dir, os.path.join(pepperdir, 'tools'), tools_files) + for tc in set(toolchains) & set(['newlib', 'glibc', 'pnacl']): if tc == 'pnacl': xarches = (None,) @@ -462,6 +482,11 @@ def GypNinjaInstall(pepperdir, toolchains): dst_dir = GetOutputToolchainLib(pepperdir, tc, xarch) InstallFiles(src_dir, dst_dir, TOOLCHAIN_LIBS[tc]) + # Copy ARM newlib components to bionic + if tc == 'newlib' and xarch == 'arm' and 'bionic' in toolchains: + bionic_dir = GetOutputToolchainLib(pepperdir, 'bionic', xarch) + InstallFiles(src_dir, bionic_dir, TOOLCHAIN_LIBS['bionic']) + if tc != 'pnacl': src_dir = GetGypToolchainLib(tc, xarch) InstallFiles(src_dir, dst_dir, ['crt1.o']) @@ -890,6 +915,8 @@ def BuildStepBuildAppEngine(pepperdir, chrome_revision): def main(args): parser = optparse.OptionParser(description=__doc__) + parser.add_option('--qemu', help='Add qemu for ARM.', + action='store_true') parser.add_option('--bionic', help='Add bionic build.', action='store_true') parser.add_option('--tar', help='Force the tar step.', @@ -995,6 +1022,10 @@ def main(args): if options.build_app_engine and getos.GetPlatform() == 'linux': BuildStepBuildAppEngine(pepperdir, chrome_revision) + if options.qemu: + qemudir = os.path.join(NACL_DIR, 'toolchain', 'linux_arm-trusted') + oshelpers.Copy(['-r', qemudir, pepperdir]) + # Archive on non-trybots. if options.archive: BuildStepArchiveBundle('build', pepper_ver, chrome_revision, nacl_revision, @@ -1012,3 +1043,4 @@ if __name__ == '__main__': sys.exit(main(sys.argv)) except KeyboardInterrupt: buildbot_common.ErrorExit('build_sdk: interrupted') + diff --git a/native_client_sdk/src/build_tools/sdk_files.list b/native_client_sdk/src/build_tools/sdk_files.list index b346b14176..0427225c20 100644 --- a/native_client_sdk/src/build_tools/sdk_files.list +++ b/native_client_sdk/src/build_tools/sdk_files.list @@ -420,6 +420,7 @@ tools/getos.py tools/host_gcc.mk tools/host_vc.mk tools/httpd.py +[linux]tools/irt_core_arm.nexe tools/irt_core_x86_32.nexe tools/irt_core_x86_64.nexe tools/lib/elf.py @@ -430,6 +431,7 @@ tools/lib/quote.py [linux,mac]tools/minidump_stackwalk tools/nacl_config.py tools/nacl_gcc.mk +[linux]tools/nacl_helper_bootstrap_arm [linux]tools/nacl_helper_bootstrap_x86_32 [linux]tools/nacl_helper_bootstrap_x86_64 tools/nacl_llvm.mk @@ -438,5 +440,6 @@ tools/ncval.py tools/oshelpers.py tools/run.py tools/sel_ldr.py +[linux]tools/sel_ldr_arm tools/sel_ldr_x86_32${EXE_EXT} tools/sel_ldr_x86_64${EXE_EXT} diff --git a/native_client_sdk/src/examples/api/media_stream_video/example.js b/native_client_sdk/src/examples/api/media_stream_video/example.js index dfd3eb9e43..5195ddf9cb 100644 --- a/native_client_sdk/src/examples/api/media_stream_video/example.js +++ b/native_client_sdk/src/examples/api/media_stream_video/example.js @@ -6,13 +6,45 @@ var stream; function success(s) { stream = s; - common.naclModule.postMessage({track: stream.getVideoTracks()[0]}); + common.naclModule.postMessage({ + command: 'init', + track: stream.getVideoTracks()[0] + }); } function failure(e) { common.logMessage("Error: " + e); } +function changeFormat(format) { + common.naclModule.postMessage({command:'format', format: format}); +} + +function changeSize(width, height) { + common.naclModule.postMessage({command:'size', width: width, height: height}); +} + function moduleDidLoad() { navigator.webkitGetUserMedia({'video': true}, success, failure); } + +function attachListeners() { + document.getElementById('YV12').addEventListener( + 'click', function() { changeFormat('YV12'); }); + document.getElementById('I420').addEventListener( + 'click', function() { changeFormat('I420'); }); + document.getElementById('BGRA').addEventListener( + 'click', function() { changeFormat('BGRA'); }); + document.getElementById('DEFAULT').addEventListener( + 'click', function() { changeFormat('DEFAULT'); }); + + document.getElementById('S72X72').addEventListener( + 'click', function() { changeSize(72, 72); }); + document.getElementById('S640X360').addEventListener( + 'click', function() { changeSize(640, 360); }); + document.getElementById('S1280X720').addEventListener( + 'click', function() { changeSize(1280, 720); }); + document.getElementById('SDEFAULT').addEventListener( + 'click', function() { changeSize(0, 0); }); + +} diff --git a/native_client_sdk/src/examples/api/media_stream_video/index.html b/native_client_sdk/src/examples/api/media_stream_video/index.html index b03fc5099e..a99d918521 100644 --- a/native_client_sdk/src/examples/api/media_stream_video/index.html +++ b/native_client_sdk/src/examples/api/media_stream_video/index.html @@ -12,13 +12,24 @@ found in the LICENSE file. <script type="text/javascript" src="common.js"></script> <script type="text/javascript" src="example.js"></script> </head> -<body data-width="640" data-height="480" {{attrs}}> +<body data-width="640" data-height="240" {{attrs}}> <h1>{{title}}</h1> <h2>Status: <code id="statusField">NO-STATUS</code></h2> <p>The MediaStream Video example demonstrates how to capture video from a webcam.</p> + Left side shows YUV frames. Right side shows BGRA frames.<br> <!-- The NaCl plugin will be embedded inside the element with id "listener". See common.js.--> <div id="listener"></div> + <h2>Format:</h2><br> + <button id="YV12">YV12</button> + <button id="I420" >I420</button> + <button id="BGRA" >BGRA</button> + <button id="DEFAULT" >DEFAULT</button> + <h2>Size:</h2><br> + <button id="S72X72" >72 x 72</button> + <button id="S640X360" >640 x 360</button> + <button id="S1280X720" >1280 x 720</button> + <button id="SDEFAULT" >DEFAULT</button> </body> </html> diff --git a/native_client_sdk/src/examples/api/media_stream_video/media_stream_video.cc b/native_client_sdk/src/examples/api/media_stream_video/media_stream_video.cc index 831d98ae36..727077bfdd 100644 --- a/native_client_sdk/src/examples/api/media_stream_video/media_stream_video.cc +++ b/native_client_sdk/src/examples/api/media_stream_video/media_stream_video.cc @@ -2,7 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "GLES2/gl2.h" +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#include <string.h> + +#include <vector> + #include "ppapi/c/pp_errors.h" #include "ppapi/c/ppb_opengles2.h" #include "ppapi/cpp/completion_callback.h" @@ -14,6 +19,7 @@ #include "ppapi/cpp/rect.h" #include "ppapi/cpp/var.h" #include "ppapi/cpp/video_frame.h" +#include "ppapi/lib/gl/gles2/gl2ext_ppapi.h" #include "ppapi/utility/completion_callback_factory.h" // When compiling natively on Windows, PostMessage can be #define-d to @@ -25,7 +31,7 @@ // Assert |context_| isn't holding any GL Errors. Done as a macro instead of a // function to preserve line number information in the failure message. #define AssertNoGLError() \ - PP_DCHECK(!gles2_if_->GetError(context_->pp_resource())); + PP_DCHECK(!glGetError()); namespace { @@ -53,35 +59,49 @@ class MediaStreamVideoDemoInstance : public pp::Instance, // pp::Graphics3DClient implementation. virtual void Graphics3DContextLost() { InitGL(); - CreateYUVTextures(); + CreateTextures(); Render(); } private: + void DrawYUV(); + void DrawRGB(); void Render(); // GL-related functions. void InitGL(); - GLuint CreateTexture(int32_t width, int32_t height, int unit); + GLuint CreateTexture(int32_t width, int32_t height, int unit, bool rgba); void CreateGLObjects(); - void CreateShader(GLuint program, GLenum type, const char* source, int size); + void CreateShader(GLuint program, GLenum type, const char* source); void PaintFinished(int32_t result); - void CreateYUVTextures(); + void CreateTextures(); + void ConfigureTrack(); + - // Callback that is invoked when new frames are recevied. + // MediaStreamVideoTrack callbacks. + void OnConfigure(int32_t result); void OnGetFrame(int32_t result, pp::VideoFrame frame); pp::Size position_size_; bool is_painting_; bool needs_paint_; + bool is_bgra_; + GLuint program_yuv_; + GLuint program_rgb_; + GLuint buffer_; GLuint texture_y_; GLuint texture_u_; GLuint texture_v_; + GLuint texture_rgb_; pp::MediaStreamVideoTrack video_track_; pp::CompletionCallbackFactory<MediaStreamVideoDemoInstance> callback_factory_; + std::vector<int32_t> attrib_list_; - // Unowned pointers. - const struct PPB_OpenGLES2* gles2_if_; + // MediaStreamVideoTrack attributes: + bool need_config_; + PP_VideoFrame_Format attrib_format_; + int32_t attrib_width_; + int32_t attrib_height_; // Owned data. pp::Graphics3D* context_; @@ -95,14 +115,21 @@ MediaStreamVideoDemoInstance::MediaStreamVideoDemoInstance( pp::Graphics3DClient(this), is_painting_(false), needs_paint_(false), + is_bgra_(false), texture_y_(0), texture_u_(0), texture_v_(0), + texture_rgb_(0), callback_factory_(this), + need_config_(false), + attrib_format_(PP_VIDEOFRAME_FORMAT_I420), + attrib_width_(0), + attrib_height_(0), context_(NULL) { - gles2_if_ = static_cast<const struct PPB_OpenGLES2*>( - module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)); - PP_DCHECK(gles2_if_); + if (!glInitializePPAPI(pp::Module::Get()->get_browser_interface())) { + LogToConsole(PP_LOGLEVEL_ERROR, pp::Var("Unable to initialize GL PPAPI!")); + assert(false); + } } MediaStreamVideoDemoInstance::~MediaStreamVideoDemoInstance() { @@ -124,19 +151,40 @@ void MediaStreamVideoDemoInstance::DidChangeView( } void MediaStreamVideoDemoInstance::HandleMessage(const pp::Var& var_message) { - if (!var_message.is_dictionary()) + if (!var_message.is_dictionary()) { + LogToConsole(PP_LOGLEVEL_ERROR, pp::Var("Invalid message!")); return; - pp::VarDictionary var_dictionary_message(var_message); - pp::Var var_track = var_dictionary_message.Get("track"); - if (!var_track.is_resource()) - return; - - pp::Resource resource_track = var_track.AsResource(); - - video_track_ = pp::MediaStreamVideoTrack(resource_track); + } - video_track_.GetFrame(callback_factory_.NewCallbackWithOutput( - &MediaStreamVideoDemoInstance::OnGetFrame)); + pp::VarDictionary var_dictionary_message(var_message); + std::string command = var_dictionary_message.Get("command").AsString(); + + if (command == "init") { + pp::Var var_track = var_dictionary_message.Get("track"); + if (!var_track.is_resource()) + return; + pp::Resource resource_track = var_track.AsResource(); + video_track_ = pp::MediaStreamVideoTrack(resource_track); + ConfigureTrack(); + } else if (command == "format") { + std::string str_format = var_dictionary_message.Get("format").AsString(); + if (str_format == "YV12") { + attrib_format_ = PP_VIDEOFRAME_FORMAT_YV12; + } else if (str_format == "I420") { + attrib_format_ = PP_VIDEOFRAME_FORMAT_I420; + } else if (str_format == "BGRA") { + attrib_format_ = PP_VIDEOFRAME_FORMAT_BGRA; + } else { + attrib_format_ = PP_VIDEOFRAME_FORMAT_UNKNOWN; + } + need_config_ = true; + } else if (command == "size") { + attrib_width_ = var_dictionary_message.Get("width").AsInt(); + attrib_height_ = var_dictionary_message.Get("height").AsInt(); + need_config_ = true; + } else { + LogToConsole(PP_LOGLEVEL_ERROR, pp::Var("Invalid command!")); + } } void MediaStreamVideoDemoInstance::InitGL() { @@ -160,11 +208,12 @@ void MediaStreamVideoDemoInstance::InitGL() { context_ = new pp::Graphics3D(this, attributes); PP_DCHECK(!context_->is_null()); + glSetCurrentContextPPAPI(context_->pp_resource()); + // Set viewport window size and clear color bit. - gles2_if_->ClearColor(context_->pp_resource(), 1, 0, 0, 1); - gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT); - gles2_if_->Viewport(context_->pp_resource(), 0, 0, - position_size_.width(), position_size_.height()); + glClearColor(1, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); + glViewport(0, 0, position_size_.width(), position_size_.height()); BindGraphics(*context_); AssertNoGLError(); @@ -172,14 +221,63 @@ void MediaStreamVideoDemoInstance::InitGL() { CreateGLObjects(); } +void MediaStreamVideoDemoInstance::DrawYUV() { + static const float kColorMatrix[9] = { + 1.1643828125f, 1.1643828125f, 1.1643828125f, + 0.0f, -0.39176171875f, 2.017234375f, + 1.59602734375f, -0.81296875f, 0.0f + }; + + glUseProgram(program_yuv_); + glUniform1i(glGetUniformLocation(program_yuv_, "y_texture"), 0); + glUniform1i(glGetUniformLocation(program_yuv_, "u_texture"), 1); + glUniform1i(glGetUniformLocation(program_yuv_, "v_texture"), 2); + glUniformMatrix3fv(glGetUniformLocation(program_yuv_, "color_matrix"), + 1, GL_FALSE, kColorMatrix); + AssertNoGLError(); + + GLint pos_location = glGetAttribLocation(program_yuv_, "a_position"); + GLint tc_location = glGetAttribLocation(program_yuv_, "a_texCoord"); + AssertNoGLError(); + glEnableVertexAttribArray(pos_location); + glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(tc_location); + glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, + static_cast<float*>(0) + 16); // Skip position coordinates. + AssertNoGLError(); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + AssertNoGLError(); +} + +void MediaStreamVideoDemoInstance::DrawRGB() { + glUseProgram(program_rgb_); + glUniform1i(glGetUniformLocation(program_rgb_, "rgb_texture"), 3); + AssertNoGLError(); + + GLint pos_location = glGetAttribLocation(program_rgb_, "a_position"); + GLint tc_location = glGetAttribLocation(program_rgb_, "a_texCoord"); + AssertNoGLError(); + glEnableVertexAttribArray(pos_location); + glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(tc_location); + glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, + static_cast<float*>(0) + 16); // Skip position coordinates. + AssertNoGLError(); + + glDrawArrays(GL_TRIANGLE_STRIP, 4, 4); +} + void MediaStreamVideoDemoInstance::Render() { PP_DCHECK(!is_painting_); is_painting_ = true; needs_paint_ = false; + if (texture_y_) { - gles2_if_->DrawArrays(context_->pp_resource(), GL_TRIANGLE_STRIP, 0, 4); + DrawRGB(); + DrawYUV(); } else { - gles2_if_->Clear(context_->pp_resource(), GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT); } pp::CompletionCallback cb = callback_factory_.NewCallback( &MediaStreamVideoDemoInstance::PaintFinished); @@ -193,30 +291,23 @@ void MediaStreamVideoDemoInstance::PaintFinished(int32_t result) { } GLuint MediaStreamVideoDemoInstance::CreateTexture( - int32_t width, int32_t height, int unit) { + int32_t width, int32_t height, int unit, bool rgba) { GLuint texture_id; - gles2_if_->GenTextures(context_->pp_resource(), 1, &texture_id); + glGenTextures(1, &texture_id); AssertNoGLError(); - // Assign parameters. - gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0 + unit); - gles2_if_->BindTexture(context_->pp_resource(), GL_TEXTURE_2D, texture_id); - gles2_if_->TexParameteri( - context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - gles2_if_->TexParameteri( - context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - GL_NEAREST); - gles2_if_->TexParameterf( - context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE); - gles2_if_->TexParameterf( - context_->pp_resource(), GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE); + // Assign parameters. + glActiveTexture(GL_TEXTURE0 + unit); + glBindTexture(GL_TEXTURE_2D, texture_id); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Allocate texture. - gles2_if_->TexImage2D( - context_->pp_resource(), GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, + rgba ? GL_BGRA_EXT : GL_LUMINANCE, + width, height, 0, + rgba ? GL_BGRA_EXT : GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); AssertNoGLError(); return texture_id; } @@ -233,7 +324,7 @@ void MediaStreamVideoDemoInstance::CreateGLObjects() { " gl_Position = a_position; \n" "}"; - static const char kFragmentShader[] = + static const char kFragmentShaderYUV[] = "precision mediump float; \n" "varying vec2 v_texCoord; \n" "uniform sampler2D y_texture; \n" @@ -250,89 +341,87 @@ void MediaStreamVideoDemoInstance::CreateGLObjects() { " gl_FragColor = vec4(rgb, 1.0); \n" "}"; - static const float kColorMatrix[9] = { - 1.1643828125f, 1.1643828125f, 1.1643828125f, - 0.0f, -0.39176171875f, 2.017234375f, - 1.59602734375f, -0.81296875f, 0.0f - }; + static const char kFragmentShaderRGB[] = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D rgb_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D(rgb_texture, v_texCoord); \n" + "}"; - PP_Resource context = context_->pp_resource(); - - // Create shader program. - GLuint program = gles2_if_->CreateProgram(context); - CreateShader(program, GL_VERTEX_SHADER, kVertexShader, sizeof(kVertexShader)); - CreateShader( - program, GL_FRAGMENT_SHADER, kFragmentShader, sizeof(kFragmentShader)); - gles2_if_->LinkProgram(context, program); - gles2_if_->UseProgram(context, program); - gles2_if_->DeleteProgram(context, program); - gles2_if_->Uniform1i( - context, gles2_if_->GetUniformLocation(context, program, "y_texture"), 0); - gles2_if_->Uniform1i( - context, gles2_if_->GetUniformLocation(context, program, "u_texture"), 1); - gles2_if_->Uniform1i( - context, gles2_if_->GetUniformLocation(context, program, "v_texture"), 2); - gles2_if_->UniformMatrix3fv( - context, - gles2_if_->GetUniformLocation(context, program, "color_matrix"), - 1, GL_FALSE, kColorMatrix); + // Create shader programs. + program_yuv_ = glCreateProgram(); + CreateShader(program_yuv_, GL_VERTEX_SHADER, kVertexShader); + CreateShader(program_yuv_, GL_FRAGMENT_SHADER, kFragmentShaderYUV); + glLinkProgram(program_yuv_); + AssertNoGLError(); + + program_rgb_ = glCreateProgram(); + CreateShader(program_rgb_, GL_VERTEX_SHADER, kVertexShader); + CreateShader(program_rgb_, GL_FRAGMENT_SHADER, kFragmentShaderRGB); + glLinkProgram(program_rgb_); AssertNoGLError(); // Assign vertex positions and texture coordinates to buffers for use in // shader program. static const float kVertices[] = { - -1, 1, -1, -1, 1, 1, 1, -1, // Position coordinates. + -1, 1, -1, -1, 0, 1, 0, -1, // Position coordinates. + 0, 1, 0, -1, 1, 1, 1, -1, // Position coordinates. + 0, 0, 0, 1, 1, 0, 1, 1, // Texture coordinates. 0, 0, 0, 1, 1, 0, 1, 1, // Texture coordinates. }; - GLuint buffer; - gles2_if_->GenBuffers(context, 1, &buffer); - gles2_if_->BindBuffer(context, GL_ARRAY_BUFFER, buffer); - gles2_if_->BufferData(context, GL_ARRAY_BUFFER, - sizeof(kVertices), kVertices, GL_STATIC_DRAW); - AssertNoGLError(); - GLint pos_location = gles2_if_->GetAttribLocation( - context, program, "a_position"); - GLint tc_location = gles2_if_->GetAttribLocation( - context, program, "a_texCoord"); - AssertNoGLError(); - gles2_if_->EnableVertexAttribArray(context, pos_location); - gles2_if_->VertexAttribPointer(context, pos_location, 2, - GL_FLOAT, GL_FALSE, 0, 0); - gles2_if_->EnableVertexAttribArray(context, tc_location); - gles2_if_->VertexAttribPointer( - context, tc_location, 2, GL_FLOAT, GL_FALSE, 0, - static_cast<float*>(0) + 8); // Skip position coordinates. + glGenBuffers(1, &buffer_); + glBindBuffer(GL_ARRAY_BUFFER, buffer_); + glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices, GL_STATIC_DRAW); AssertNoGLError(); } void MediaStreamVideoDemoInstance::CreateShader( - GLuint program, GLenum type, const char* source, int size) { - PP_Resource context = context_->pp_resource(); - GLuint shader = gles2_if_->CreateShader(context, type); - gles2_if_->ShaderSource(context, shader, 1, &source, &size); - gles2_if_->CompileShader(context, shader); - gles2_if_->AttachShader(context, program, shader); - gles2_if_->DeleteShader(context, shader); + GLuint program, GLenum type, const char* source) { + GLuint shader = glCreateShader(type); + GLint length = strlen(source) + 1; + glShaderSource(shader, 1, &source, &length); + glCompileShader(shader); + glAttachShader(program, shader); + glDeleteShader(shader); } -void MediaStreamVideoDemoInstance::CreateYUVTextures() { +void MediaStreamVideoDemoInstance::CreateTextures() { int32_t width = frame_size_.width(); int32_t height = frame_size_.height(); if (width == 0 || height == 0) return; if (texture_y_) - gles2_if_->DeleteTextures(context_->pp_resource(), 1, &texture_y_); + glDeleteTextures(1, &texture_y_); if (texture_u_) - gles2_if_->DeleteTextures(context_->pp_resource(), 1, &texture_u_); + glDeleteTextures(1, &texture_u_); if (texture_v_) - gles2_if_->DeleteTextures(context_->pp_resource(), 1, &texture_v_); - texture_y_ = CreateTexture(width, height, 0); + glDeleteTextures(1, &texture_v_); + if (texture_rgb_) + glDeleteTextures(1, &texture_rgb_); + texture_y_ = CreateTexture(width, height, 0, false); + + texture_u_ = CreateTexture(width / 2, height / 2, 1, false); + texture_v_ = CreateTexture(width / 2, height / 2, 2, false); + texture_rgb_ = CreateTexture(width, height, 3, true); +} - width /= 2; - height /= 2; - texture_u_ = CreateTexture(width, height, 1); - texture_v_ = CreateTexture(width, height, 2); +void MediaStreamVideoDemoInstance::ConfigureTrack() { + const int32_t attrib_list[] = { + PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT, attrib_format_, + PP_MEDIASTREAMVIDEOTRACK_ATTRIB_WIDTH, attrib_width_, + PP_MEDIASTREAMVIDEOTRACK_ATTRIB_HEIGHT, attrib_height_, + PP_MEDIASTREAMVIDEOTRACK_ATTRIB_NONE + }; + video_track_.Configure(attrib_list, callback_factory_.NewCallback( + &MediaStreamVideoDemoInstance::OnConfigure)); +} + +void MediaStreamVideoDemoInstance::OnConfigure(int32_t result) { + video_track_.GetFrame(callback_factory_.NewCallbackWithOutput( + &MediaStreamVideoDemoInstance::OnGetFrame)); } void MediaStreamVideoDemoInstance::OnGetFrame( @@ -341,33 +430,39 @@ void MediaStreamVideoDemoInstance::OnGetFrame( return; const char* data = static_cast<const char*>(frame.GetDataBuffer()); pp::Size size; - PP_DCHECK(frame.GetSize(&size)); + frame.GetSize(&size); + if (size != frame_size_) { frame_size_ = size; - CreateYUVTextures(); + CreateTextures(); } + is_bgra_ = (frame.GetFormat() == PP_VIDEOFRAME_FORMAT_BGRA); + int32_t width = frame_size_.width(); int32_t height = frame_size_.height(); - gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE0); - gles2_if_->TexSubImage2D( - context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, - GL_LUMINANCE, GL_UNSIGNED_BYTE, data); - - data += width * height; - width /= 2; - height /= 2; - - gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE1); - gles2_if_->TexSubImage2D( - context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, - GL_LUMINANCE, GL_UNSIGNED_BYTE, data); - - data += width * height; - gles2_if_->ActiveTexture(context_->pp_resource(), GL_TEXTURE2); - gles2_if_->TexSubImage2D( - context_->pp_resource(), GL_TEXTURE_2D, 0, 0, 0, width, height, - GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + if (!is_bgra_) { + glActiveTexture(GL_TEXTURE0); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, + GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + + data += width * height; + width /= 2; + height /= 2; + + glActiveTexture(GL_TEXTURE1); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, + GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + + data += width * height; + glActiveTexture(GL_TEXTURE2); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, + GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + } else { + glActiveTexture(GL_TEXTURE3); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, + GL_BGRA_EXT, GL_UNSIGNED_BYTE, data); + } if (is_painting_) needs_paint_ = true; @@ -375,8 +470,13 @@ void MediaStreamVideoDemoInstance::OnGetFrame( Render(); video_track_.RecycleFrame(frame); - video_track_.GetFrame(callback_factory_.NewCallbackWithOutput( - &MediaStreamVideoDemoInstance::OnGetFrame)); + if (need_config_) { + ConfigureTrack(); + need_config_ = false; + } else { + video_track_.GetFrame(callback_factory_.NewCallbackWithOutput( + &MediaStreamVideoDemoInstance::OnGetFrame)); + } } pp::Instance* MediaStreamVideoModule::CreateInstance(PP_Instance instance) { diff --git a/native_client_sdk/src/gonacl_appengine/gonacl.py b/native_client_sdk/src/gonacl_appengine/gonacl.py index 69892e165f..0a093fb439 100644 --- a/native_client_sdk/src/gonacl_appengine/gonacl.py +++ b/native_client_sdk/src/gonacl_appengine/gonacl.py @@ -5,5 +5,5 @@ import webapp2 application = webapp2.WSGIApplication([ webapp2.Route('/', webapp2.RedirectHandler, defaults={ - '_uri': 'http://developers.google.com/native-client/dev'}), + '_uri': 'http://developer.chrome.com/native-client'}), ], debug=True) diff --git a/native_client_sdk/src/libraries/nacl_io/devfs/tty_node.cc b/native_client_sdk/src/libraries/nacl_io/devfs/tty_node.cc index bb9361349f..fe4bbfdc96 100644 --- a/native_client_sdk/src/libraries/nacl_io/devfs/tty_node.cc +++ b/native_client_sdk/src/libraries/nacl_io/devfs/tty_node.cc @@ -53,8 +53,10 @@ void TtyNode::InitTermios() { termios_.c_cflag = CREAD | 077; termios_.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN; +#if !defined(__BIONIC__) termios_.c_ispeed = B38400; termios_.c_ospeed = B38400; +#endif termios_.c_cc[VINTR] = 3; termios_.c_cc[VQUIT] = 28; termios_.c_cc[VERASE] = 127; diff --git a/native_client_sdk/src/libraries/nacl_io/h_errno.c b/native_client_sdk/src/libraries/nacl_io/h_errno.c new file mode 100644 index 0000000000..114878dbbd --- /dev/null +++ b/native_client_sdk/src/libraries/nacl_io/h_errno.c @@ -0,0 +1,39 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "nacl_io/ossocket.h" + +#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) + +#include <stdlib.h> +#include <pthread.h> + +static pthread_key_t s_h_errno_key; +static pthread_once_t s_h_errno_once = PTHREAD_ONCE_INIT; + +static void __h_errno_create() { + pthread_key_create(&s_h_errno_key, NULL); +} + +int *__h_errno_location() { + int* h_errno_ptr; + pthread_once(&s_h_errno_once, __h_errno_create); + h_errno_ptr = (int *) pthread_getspecific(s_h_errno_key); + + if (NULL == h_errno_ptr) { + h_errno_ptr = (int *) malloc(sizeof(int)); + pthread_setspecific(s_h_errno_key, h_errno_ptr); + *h_errno_ptr = 0; + } + + return h_errno_ptr; +} + +#if defined(__BIONIC__) +int *__get_h_errno() { + return __h_errno_location(); +} +#endif + +#endif // defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) diff --git a/native_client_sdk/src/libraries/nacl_io/h_errno.cc b/native_client_sdk/src/libraries/nacl_io/h_errno.cc deleted file mode 100644 index 5f328edd16..0000000000 --- a/native_client_sdk/src/libraries/nacl_io/h_errno.cc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "nacl_io/ossocket.h" - -#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) - -static __thread int __h_errno__; - -extern "C" int *__h_errno_location() { - return &__h_errno__; -} - -#endif // defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) diff --git a/native_client_sdk/src/libraries/nacl_io/in6_addr.c b/native_client_sdk/src/libraries/nacl_io/in6_addr.c index a09ea7b092..71518a5795 100644 --- a/native_client_sdk/src/libraries/nacl_io/in6_addr.c +++ b/native_client_sdk/src/libraries/nacl_io/in6_addr.c @@ -3,7 +3,7 @@ * found in the LICENSE file. */ #include "nacl_io/ossocket.h" -#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) +#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) && !defined(__BIONIC__) #include <netinet/in.h> @@ -18,4 +18,4 @@ const struct in6_addr in6addr_linklocal_allnodes = { const struct in6_addr in6addr_linklocal_allrouters = { {{0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}}}; -#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) */ +#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) ... */ diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc index 680eaac097..0cd8c10f49 100644 --- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc +++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc @@ -1029,28 +1029,24 @@ int KernelProxy::sigaction(int signum, const struct sigaction* action, int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout) { - fd_set ignore; std::vector<pollfd> pollfds; - // Simplify logic, by using an IGNORE set for any undefined set - FD_ZERO(&ignore); - if (NULL == readfds) - readfds = &ignore; - if (NULL == writefds) - writefds = &ignore; - if (NULL == exceptfds) - exceptfds = &ignore; - for (int fd = 0; fd < nfds; fd++) { int events = 0; - if (FD_ISSET(fd, readfds)) + if (readfds && FD_ISSET(fd, readfds)) { events |= POLLIN; + FD_CLR(fd, readfds); + } - if (FD_ISSET(fd, writefds)) + if (writefds && FD_ISSET(fd, writefds)) { events |= POLLOUT; + FD_CLR(fd, writefds); + } - if (FD_ISSET(fd, exceptfds)) + if (exceptfds && FD_ISSET(fd, exceptfds)) { events |= POLLERR | POLLHUP; + FD_CLR(fd, exceptfds); + } if (events) { pollfd info; @@ -1060,10 +1056,6 @@ int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds, } } - FD_ZERO(readfds); - FD_ZERO(writefds); - FD_ZERO(exceptfds); - // NULL timeout signals wait forever. int ms_timeout = -1; if (timeout != NULL) { diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap.h b/native_client_sdk/src/libraries/nacl_io/kernel_wrap.h index e8e4e99323..6211e8cca4 100644 --- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap.h +++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap.h @@ -64,7 +64,12 @@ int fsync(int fd); int ftruncate(int fd, off_t length) NOTHROW; char* NAME(getcwd)(char* buf, getcwd_size_t size) NOTHROW; char* getwd(char* buf) NOTHROW; +#if !defined(__BIONIC__) int getdents(int fd, void* buf, unsigned int count) NOTHROW; +#else +struct dirent; +int getdents(unsigned int fd, struct dirent* buf, unsigned int count) NOTHROW; +#endif int NAME(isatty)(int fd) NOTHROW; int lchown(const char* path, uid_t owner, gid_t group) NOTHROW; int link(const char* oldpath, const char* newpath) NOTHROW; diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_bionic.cc b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_bionic.cc new file mode 100644 index 0000000000..a72deb5b43 --- /dev/null +++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_bionic.cc @@ -0,0 +1,520 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <sys/types.h> // Include something that will define __BIONIC__. + +// The entire file is wrapped in this #if. We do this so this .cc file can be +// compiled, even on a non-bionic build. + +#if defined(__native_client__) && defined(__BIONIC__) +#include <alloca.h> +#include <assert.h> +#include <dirent.h> +#include <errno.h> +#include <irt_syscalls.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/time.h> + +#include "nacl_io/kernel_intercept.h" +#include "nacl_io/kernel_wrap.h" +#include "nacl_io/kernel_wrap_real.h" +#include "nacl_io/osmman.h" + +namespace { + +void stat_to_nacl_stat(const struct stat* buf, nacl_abi_stat* nacl_buf) { + memset(nacl_buf, 0, sizeof(struct nacl_abi_stat)); + nacl_buf->nacl_abi_st_dev = buf->st_dev; + nacl_buf->nacl_abi_st_ino = buf->st_ino; + nacl_buf->nacl_abi_st_mode = buf->st_mode; + nacl_buf->nacl_abi_st_nlink = buf->st_nlink; + nacl_buf->nacl_abi_st_uid = buf->st_uid; + nacl_buf->nacl_abi_st_gid = buf->st_gid; + nacl_buf->nacl_abi_st_rdev = buf->st_rdev; + nacl_buf->nacl_abi_st_size = buf->st_size; + nacl_buf->nacl_abi_st_blksize = buf->st_blksize; + nacl_buf->nacl_abi_st_blocks = buf->st_blocks; + nacl_buf->nacl_abi_st_atime = buf->st_atime; + nacl_buf->nacl_abi_st_mtime = buf->st_mtime; + nacl_buf->nacl_abi_st_ctime = buf->st_ctime; +} + +void nacl_stat_to_stat(const nacl_abi_stat* nacl_buf, struct stat* buf) { + memset(buf, 0, sizeof(struct stat)); + buf->st_dev = nacl_buf->nacl_abi_st_dev; + buf->st_ino = nacl_buf->nacl_abi_st_ino; + buf->st_mode = nacl_buf->nacl_abi_st_mode; + buf->st_nlink = nacl_buf->nacl_abi_st_nlink; + buf->st_uid = nacl_buf->nacl_abi_st_uid; + buf->st_gid = nacl_buf->nacl_abi_st_gid; + buf->st_rdev = nacl_buf->nacl_abi_st_rdev; + buf->st_size = nacl_buf->nacl_abi_st_size ; + buf->st_blksize = nacl_buf->nacl_abi_st_blksize; + buf->st_blocks = nacl_buf->nacl_abi_st_blocks; + buf->st_atime = nacl_buf->nacl_abi_st_atime; + buf->st_mtime = nacl_buf->nacl_abi_st_mtime; + buf->st_ctime = nacl_buf->nacl_abi_st_ctime; +} + +} // namespace + +// From native_client/src/trusted/service_runtime/include/sys/dirent.h + +#ifndef nacl_abi___ino_t_defined +#define nacl_abi___ino_t_defined +typedef int64_t nacl_abi___ino_t; +typedef nacl_abi___ino_t nacl_abi_ino_t; +#endif + +#ifndef nacl_abi___off_t_defined +#define nacl_abi___off_t_defined +typedef int64_t nacl_abi__off_t; +typedef nacl_abi__off_t nacl_abi_off_t; +#endif + +/* We need a way to define the maximum size of a name. */ +#ifndef MAXNAMLEN +# ifdef NAME_MAX +# define MAXNAMLEN NAME_MAX +# else +# define MAXNAMLEN 255 +# endif +#endif + +struct nacl_abi_dirent { + nacl_abi_ino_t nacl_abi_d_ino; + nacl_abi_off_t nacl_abi_d_off; + uint16_t nacl_abi_d_reclen; + char nacl_abi_d_name[MAXNAMLEN + 1]; +}; + +static const int d_name_shift = offsetof (dirent, d_name) - + offsetof (struct nacl_abi_dirent, nacl_abi_d_name); + +EXTERN_C_BEGIN + +// Macro to get the REAL function pointer +#define REAL(name) __nacl_irt_##name##_real + +// Macro to get the WRAP function +#define WRAP(name) __nacl_irt_##name##_wrap + +// Declare REAL function pointer. +#define DECLARE_REAL_PTR(name) \ + typeof(__nacl_irt_##name) REAL(name); + +// Assign the REAL function pointer. +#define ASSIGN_REAL_PTR(name) \ + REAL(name) = __nacl_irt_##name; + +// Switch IRT's pointer to the REAL pointer +#define USE_REAL(name) \ + __nacl_irt_##name = (typeof(__nacl_irt_##name)) REAL(name) + +// Switch IRT's pointer to the WRAP function +#define USE_WRAP(name) \ + __nacl_irt_##name = (typeof(__nacl_irt_##name)) WRAP(name) + + +#define EXPAND_SYMBOL_LIST_OPERATION(OP) \ + OP(chdir); \ + OP(close); \ + OP(dup); \ + OP(dup2); \ + OP(exit); \ + OP(fchdir); \ + OP(fchmod); \ + OP(fdatasync); \ + OP(fstat); \ + OP(fsync); \ + OP(getcwd); \ + OP(getdents); \ + OP(isatty); \ + OP(lstat); \ + OP(mkdir); \ + OP(mmap); \ + OP(munmap); \ + OP(open); \ + OP(open_resource); \ + OP(poll); \ + OP(read); \ + OP(readlink); \ + OP(rmdir); \ + OP(seek); \ + OP(stat); \ + OP(truncate); \ + OP(write); \ + + +EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR); + +int WRAP(chdir)(const char* pathname) { + return (ki_chdir(pathname)) ? errno : 0; +} + +int WRAP(close)(int fd) { + return (ki_close(fd) < 0) ? errno : 0; +} + +int WRAP(dup)(int fd, int* newfd) NOTHROW { + *newfd = ki_dup(fd); + return (*newfd < 0) ? errno : 0; +} + +int WRAP(dup2)(int fd, int newfd) NOTHROW { + return (ki_dup2(fd, newfd) < 0) ? errno : 0; +} + +void WRAP(exit)(int status) { + ki_exit(status); +} + +int WRAP(fchdir)(int fd) NOTHROW { + return (ki_fchdir(fd)) ? errno : 0; +} + +int WRAP(fchmod)(int fd, mode_t mode) NOTHROW { + return (ki_fchmod(fd, mode)) ? errno : 0; +} + +int WRAP(fdatasync)(int fd) NOTHROW { + return (ki_fdatasync(fd)) ? errno : 0; +} + +int WRAP(fstat)(int fd, struct nacl_abi_stat *nacl_buf) { + struct stat buf; + memset(&buf, 0, sizeof(struct stat)); + int res = ki_fstat(fd, &buf); + if (res < 0) + return errno; + stat_to_nacl_stat(&buf, nacl_buf); + return 0; +} + +int WRAP(fsync)(int fd) NOTHROW { + return (ki_fsync(fd)) ? errno : 0; +} + +char* WRAP(getcwd)(char* buf, size_t size) { + if (ki_getcwd(buf, size) == NULL) + return errno; + return 0; +} + +int WRAP(getdents)(int fd, dirent* nacl_buf, size_t nacl_count, size_t *nread) { + int nacl_offset = 0; + // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s). + // nacl_abi_dirent(s) are smaller than dirent(s), so nacl_count bytes buffer + // is enough + char* buf = (char*)alloca(nacl_count); + int offset = 0; + int count; + + count = ki_getdents(fd, buf, nacl_count); + if (count < 0) + return errno; + + while (offset < count) { + dirent* d = (dirent*)(buf + offset); + nacl_abi_dirent* nacl_d = (nacl_abi_dirent*)((char*)nacl_buf + nacl_offset); + nacl_d->nacl_abi_d_ino = d->d_ino; + nacl_d->nacl_abi_d_off = d->d_off; + nacl_d->nacl_abi_d_reclen = d->d_reclen - d_name_shift; + size_t d_name_len = d->d_reclen - offsetof(dirent, d_name); + memcpy(nacl_d->nacl_abi_d_name, d->d_name, d_name_len); + + offset += d->d_reclen; + nacl_offset += nacl_d->nacl_abi_d_reclen; + } + + *nread = nacl_offset; + return 0; +} + +int WRAP(isatty)(int fd, int* result) { + *result = ki_isatty(fd); + if (*result == 1) + return errno; + return 0; +} + +int WRAP(lstat)(const char *path, struct nacl_abi_stat* nacl_buf) { + struct stat buf; + memset(&buf, 0, sizeof(struct stat)); + int res = ki_lstat(path, &buf); + if (res < 0) + return errno; + stat_to_nacl_stat(&buf, nacl_buf); + return 0; +} + +int WRAP(mkdir)(const char* pathname, mode_t mode) { + return (ki_mkdir(pathname, mode)) ? errno : 0; +} + +int WRAP(mmap)(void** addr, size_t length, int prot, int flags, int fd, + int64_t offset) { + if (flags & MAP_ANONYMOUS) + return REAL(mmap)(addr, length, prot, flags, fd, offset); + + *addr = ki_mmap(*addr, length, prot, flags, fd, offset); + return *addr == (void*)-1 ? errno : 0; +} + +int WRAP(munmap)(void* addr, size_t length) { + // Always let the real munmap run on the address range. It is not an error if + // there are no mapped pages in that range. + ki_munmap(addr, length); + return REAL(munmap)(addr, length); +} + +int WRAP(open)(const char* pathname, int oflag, mode_t cmode, int* newfd) { + *newfd = ki_open(pathname, oflag); + return (*newfd < 0) ? errno : 0; +} + +int WRAP(open_resource)(const char* file, int* fd) { + *fd = ki_open_resource(file); + return (*fd < 0) ? errno : 0; +} + +int WRAP(poll)(struct pollfd *fds, nfds_t nfds, int timeout, int* count) { + *count = ki_poll(fds, nfds, timeout); + return (*count < 0) ? errno : 0; + +} + +int WRAP(read)(int fd, void *buf, size_t count, size_t *nread) { + ssize_t signed_nread = ki_read(fd, buf, count); + *nread = static_cast<size_t>(signed_nread); + return (signed_nread < 0) ? errno : 0; +} + +int WRAP(readlink)(const char* path, char* buf, size_t count, size_t* nread) { + ssize_t signed_nread = ki_readlink(path, buf, count); + *nread = static_cast<size_t>(signed_nread); + return (signed_nread < 0) ? errno : 0; +} + +int WRAP(rmdir)(const char* pathname) { + return (ki_rmdir(pathname) < 0) ? errno : 0; +} + +int WRAP(seek)(int fd, off64_t offset, int whence, int64_t* new_offset) { + *new_offset = ki_lseek(fd, offset, whence); + return (*new_offset < 0) ? errno : 0; +} + +int WRAP(select)(int nfds, fd_set* readfds, fd_set* writefds, + fd_set* exceptfds, struct timeval* timeout, int* count) { + *count = ki_select(nfds, readfds, writefds, exceptfds, timeout); + return (*count < 0) ? errno : 0; +} + +int WRAP(stat)(const char *pathname, struct nacl_abi_stat *nacl_buf) { + struct stat buf; + memset(&buf, 0, sizeof(struct stat)); + int res = ki_stat(pathname, &buf); + if (res < 0) + return errno; + stat_to_nacl_stat(&buf, nacl_buf); + return 0; +} + +int WRAP(truncate)(const char *name, int64_t len) { + return (ki_truncate(name, len)) ? errno : 0; +} + +int WRAP(write)(int fd, const void* buf, size_t count, size_t* nwrote) { + ssize_t signed_nwrote = ki_write(fd, buf, count); + *nwrote = static_cast<size_t>(signed_nwrote); + return (signed_nwrote < 0) ? errno : 0; +} + +static void assign_real_pointers() { + static bool assigned = false; + if (!assigned) { + EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR) + assigned = true; + } +} + +#define CHECK_REAL(func) \ + if (!REAL(func)) \ + assign_real_pointers(); + +// "real" functions, i.e. the unwrapped original functions. + +int _real_close(int fd) { + CHECK_REAL(close); + return REAL(close)(fd); +} + +void _real_exit(int status) { + REAL(exit)(status); +} + +int _real_fchdir(int fd) { + CHECK_REAL(fchdir); + return REAL(fchdir)(fd); +} + +int _real_fchmod(int fd, mode_t mode) { + CHECK_REAL(fchmod); + return REAL(fchmod)(fd, mode); +} + +int _real_fdatasync(int fd) { + CHECK_REAL(fdatasync); + return REAL(fdatasync)(fd); +} + +int _real_fstat(int fd, struct stat* buf) { + struct nacl_abi_stat st; + CHECK_REAL(fstat); + + int err = REAL(fstat)(fd, (struct stat*) &st); + if (err) { + errno = err; + return -1; + } + + nacl_stat_to_stat(&st, buf); + return 0; +} + +int _real_fsync(int fd) { + CHECK_REAL(fsync); + return REAL(fsync)(fd); +} + +int _real_getdents(int fd, void* buf, size_t count, size_t* nread) { + // "buf" contains dirent(s); "nacl_buf" contains nacl_abi_dirent(s). + // See WRAP(getdents) above. + char* nacl_buf = (char*)alloca(count); + size_t offset = 0; + size_t nacl_offset = 0; + size_t nacl_nread; + CHECK_REAL(getdents); + int err = REAL(getdents)(fd, (dirent*)nacl_buf, count, &nacl_nread); + if (err) + return err; + + while (nacl_offset < nacl_nread) { + dirent* d = (dirent*)((char*)buf + offset); + nacl_abi_dirent* nacl_d = (nacl_abi_dirent*)(nacl_buf + nacl_offset); + d->d_ino = nacl_d->nacl_abi_d_ino; + d->d_off = nacl_d->nacl_abi_d_off; + d->d_reclen = nacl_d->nacl_abi_d_reclen + d_name_shift; + size_t d_name_len = nacl_d->nacl_abi_d_reclen - + offsetof(nacl_abi_dirent, nacl_abi_d_name); + memcpy(d->d_name, nacl_d->nacl_abi_d_name, d_name_len); + + offset += d->d_reclen; + offset += nacl_d->nacl_abi_d_reclen; + } + + *nread = offset; + return 0; +} + +int _real_isatty(int fd, int* result) { + *result = isatty(fd); + return *result ? 0 : -1; +} + +int _real_lseek(int fd, int64_t offset, int whence, int64_t* new_offset) { + CHECK_REAL(seek); + nacl_abi_off_t nacl_new_offs; + int ret = REAL(seek)(fd, offset, whence, &nacl_new_offs); + *new_offset = static_cast<off_t>(nacl_new_offs); + return ret; +} + +int _real_lstat(const char* path, struct stat* buf) { + struct nacl_abi_stat st; + CHECK_REAL(fstat); + + int err = REAL(lstat)(path, (struct stat*) &st); + if (err) { + errno = err; + return -1; + } + + nacl_stat_to_stat(&st, buf); + return 0; +} + + +int _real_mkdir(const char* pathname, mode_t mode) { + CHECK_REAL(mkdir); + return REAL(mkdir)(pathname, mode); +} + +int _real_mmap(void** addr, size_t length, int prot, int flags, int fd, + int64_t offset) { + CHECK_REAL(mmap); + return REAL(mmap)(addr, length, prot, flags, fd, offset); +} + +int _real_munmap(void* addr, size_t length) { + CHECK_REAL(munmap); + return REAL(munmap)(addr, length); +} + +int _real_open(const char* pathname, int oflag, mode_t cmode, int* newfd) { + CHECK_REAL(open); + return REAL(open)(pathname, oflag, cmode, newfd); +} + +int _real_open_resource(const char* file, int* fd) { + CHECK_REAL(open_resource); + return REAL(open_resource)(file, fd); +} + +int _real_read(int fd, void *buf, size_t count, size_t *nread) { + CHECK_REAL(read); + return REAL(read)(fd, buf, count, nread); +} + +int _real_readlink(const char *path, char* buf, size_t count, size_t* nread) { + CHECK_REAL(readlink); + return REAL(readlink)(path, buf, count, nread); +} + +int _real_rmdir(const char* pathname) { + CHECK_REAL(rmdir); + return REAL(rmdir)(pathname); +} + +int _real_truncate(const char* pathname, int64_t len) { + CHECK_REAL(truncate); + return REAL(truncate)(pathname, len); +} + +int _real_write(int fd, const void *buf, size_t count, size_t *nwrote) { + CHECK_REAL(write); + return REAL(write)(fd, buf, count, nwrote); +} + +static bool s_wrapped = false; +void kernel_wrap_init() { + if (!s_wrapped) { + assign_real_pointers(); + EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP) + s_wrapped = true; + } +} + +void kernel_wrap_uninit() { + if (s_wrapped) { + EXPAND_SYMBOL_LIST_OPERATION(USE_REAL) + s_wrapped = false; + } +} + +EXTERN_C_END + +#endif // defined(__native_client__) && defined(__GLIBC__) diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc index 8090123516..049e53b492 100644 --- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc +++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc @@ -6,7 +6,7 @@ // The entire file is wrapped in this #if. We do this so this .cc file can be // compiled, even on a non-newlib build. -#if defined(__native_client__) && !defined(__GLIBC__) +#if defined(__native_client__) && !defined(__GLIBC__) && !defined(__BIONIC__) #include "nacl_io/kernel_wrap.h" @@ -161,7 +161,7 @@ int WRAP(ftruncate)(int fd, off_t length) { int WRAP(isatty)(int fd, int* result) { *result = ki_isatty(fd); - if (*result == 1) + if (*result == 0) return errno; return 0; } @@ -357,4 +357,4 @@ void kernel_wrap_uninit() { EXTERN_C_END -#endif // defined(__native_client__) && !defined(__GLIBC__) +#endif // defined(__native_client__) && !defined(__GLIBC__) ... diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h index f46f6cc547..68e3345f37 100644 --- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h +++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h @@ -11,15 +11,16 @@ EXTERN_C_BEGIN +/* NOTE: We do not use off_t because it may be 32 or 64 bit */ int _real_close(int fd); void _real_exit(int status); int _real_fstat(int fd, struct stat *buf); int _real_getdents(int fd, void* nacl_buf, size_t nacl_count, size_t *nread); int _real_isatty(int fd, int* result); -int _real_lseek(int fd, off_t offset, int whence, off_t* new_offset); +int _real_lseek(int fd, int64_t offset, int whence, int64_t* new_offset); int _real_mkdir(const char* pathname, mode_t mode); int _real_mmap(void** addr, size_t length, int prot, int flags, int fd, - off_t offset); + int64_t offset); int _real_munmap(void* addr, size_t length); int _real_open(const char* pathname, int oflag, mode_t cmode, int* newfd); int _real_open_resource(const char* file, int* fd); diff --git a/native_client_sdk/src/libraries/nacl_io/library.dsc b/native_client_sdk/src/libraries/nacl_io/library.dsc index 5509382a8a..14855ccb9f 100644 --- a/native_client_sdk/src/libraries/nacl_io/library.dsc +++ b/native_client_sdk/src/libraries/nacl_io/library.dsc @@ -1,5 +1,5 @@ { - 'TOOLS': ['newlib', 'glibc', 'pnacl', 'linux'], + 'TOOLS': ['bionic', 'newlib', 'glibc', 'pnacl', 'linux'], 'SEARCH': [ '.', 'pepper', @@ -24,7 +24,7 @@ "fusefs/fuse_fs.cc", "fusefs/fuse_fs_factory.cc", "getdents_helper.cc", - "h_errno.cc", + "h_errno.c", "host_resolver.cc", "html5fs/html5_fs.cc", "html5fs/html5_fs_node.cc", @@ -35,6 +35,7 @@ "kernel_intercept.cc", "kernel_object.cc", "kernel_proxy.cc", + "kernel_wrap_bionic.cc", "kernel_wrap_dummy.cc", "kernel_wrap_glibc.cc", "kernel_wrap_newlib.cc", diff --git a/native_client_sdk/src/libraries/nacl_io/osdirent.h b/native_client_sdk/src/libraries/nacl_io/osdirent.h index 10e07063c4..2da0f3992e 100644 --- a/native_client_sdk/src/libraries/nacl_io/osdirent.h +++ b/native_client_sdk/src/libraries/nacl_io/osdirent.h @@ -19,6 +19,7 @@ struct dirent { #else +#include <sys/types.h> #include <dirent.h> #endif diff --git a/native_client_sdk/src/libraries/nacl_io/ossignal.h b/native_client_sdk/src/libraries/nacl_io/ossignal.h index 796abd9a62..146f1cead5 100644 --- a/native_client_sdk/src/libraries/nacl_io/ossignal.h +++ b/native_client_sdk/src/libraries/nacl_io/ossignal.h @@ -7,7 +7,7 @@ #if !defined(WIN23) #include <signal.h> -#if defined(__GLIBC__) +#if defined(__GLIBC__) || defined(__BIONIC__) typedef __sighandler_t sighandler_t; #else typedef _sig_func_ptr sighandler_t; diff --git a/native_client_sdk/src/libraries/nacl_io/passthroughfs/passthrough_fs.cc b/native_client_sdk/src/libraries/nacl_io/passthroughfs/passthrough_fs.cc index ebbec7d042..8b3bcab9f0 100644 --- a/native_client_sdk/src/libraries/nacl_io/passthroughfs/passthrough_fs.cc +++ b/native_client_sdk/src/libraries/nacl_io/passthroughfs/passthrough_fs.cc @@ -33,7 +33,7 @@ class PassthroughFsNode : public Node { int* out_bytes) { *out_bytes = 0; - off_t new_offset; + int64_t new_offset; int err = _real_lseek(real_fd_, attr.offs, 0, &new_offset); if (err) return err; @@ -53,7 +53,7 @@ class PassthroughFsNode : public Node { int* out_bytes) { *out_bytes = 0; - off_t new_offset; + int64_t new_offset; int err = _real_lseek(real_fd_, attr.offs, 0, &new_offset); if (err) return err; diff --git a/native_client_sdk/src/libraries/nacl_io/socket/socket_node.cc b/native_client_sdk/src/libraries/nacl_io/socket/socket_node.cc index e296117b48..98de7f623f 100644 --- a/native_client_sdk/src/libraries/nacl_io/socket/socket_node.cc +++ b/native_client_sdk/src/libraries/nacl_io/socket/socket_node.cc @@ -266,6 +266,8 @@ Error SocketNode::SetSockOpt(int lvl, int optname, const void* optval, socklen_t len) { + size_t buflen = static_cast<size_t>(len); + if (lvl != SOL_SOCKET) return ENOPROTOOPT; @@ -276,14 +278,14 @@ Error SocketNode::SetSockOpt(int lvl, // SO_REUSEADDR is effectivly always on since we can't // disable it with PPAPI sockets. Just return success // here regardless. - if (len < sizeof(int)) + if (buflen < sizeof(int)) return EINVAL; return 0; } case SO_LINGER: { // Not supported by the PPAPI interface but we preserve // the settings and pretend to support it. - if (len < sizeof(struct linger)) + if (buflen < sizeof(struct linger)) return EINVAL; struct linger new_linger = *static_cast<const linger*>(optval); // Don't allow setting linger to be enabled until we @@ -298,7 +300,7 @@ Error SocketNode::SetSockOpt(int lvl, case SO_KEEPALIVE: { // Not supported by the PPAPI interface but we preserve // the flag and pretend to support it. - if (len < sizeof(int)) + if (buflen < sizeof(int)) return EINVAL; int value = *static_cast<const int*>(optval); keep_alive_ = value != 0; diff --git a/native_client_sdk/src/libraries/nacl_io/socket/tcp_node.cc b/native_client_sdk/src/libraries/nacl_io/socket/tcp_node.cc index bb9c171813..06e45e67ec 100644 --- a/native_client_sdk/src/libraries/nacl_io/socket/tcp_node.cc +++ b/native_client_sdk/src/libraries/nacl_io/socket/tcp_node.cc @@ -318,7 +318,7 @@ Error TcpNode::GetSockOpt(int lvl, int optname, void* optval, socklen_t* len) { if (lvl == IPPROTO_TCP && optname == TCP_NODELAY) { AUTO_LOCK(node_lock_); int value = tcp_nodelay_; - socklen_t value_len = sizeof(value); + socklen_t value_len = static_cast<socklen_t>(sizeof(value)); int copy_bytes = std::min(value_len, *len); memcpy(optval, &value, copy_bytes); *len = value_len; @@ -345,7 +345,7 @@ Error TcpNode::SetSockOpt(int lvl, const void* optval, socklen_t len) { if (lvl == IPPROTO_TCP && optname == TCP_NODELAY) { - if (len < sizeof(int)) + if (static_cast<size_t>(len) < sizeof(int)) return EINVAL; AUTO_LOCK(node_lock_); tcp_nodelay_ = *static_cast<const int*>(optval) != 0; diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/access.c b/native_client_sdk/src/libraries/nacl_io/syscalls/access.c index 041f80dba1..6c94ac2c1f 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/access.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/access.c @@ -5,8 +5,7 @@ #include "nacl_io/kernel_intercept.h" #include "nacl_io/kernel_wrap.h" -#if !defined(__native_client__) || defined(__GLIBC__) -// GLIBC-only entry point. +#if !defined(__native_client__) || defined(__GLIBC__) || defined(__BIONIC__) // TODO(sbc): remove once this bug gets fixed: // https://code.google.com/p/nativeclient/issues/detail?id=3709 int access(const char* path, int amode) { diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/cfgetispeed.c b/native_client_sdk/src/libraries/nacl_io/syscalls/cfgetispeed.c index 747e234f9f..2d66d7ee7a 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/cfgetispeed.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/cfgetispeed.c @@ -2,9 +2,19 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include <sys/types.h> +/* + * Include something that will define __BIONIC__, then wrap the entire file + * in this #if, so this file will be compiled on a non-bionic build. + */ + +#if !defined(__BIONIC__) + #include "nacl_io/kernel_intercept.h" #include "nacl_io/kernel_wrap.h" speed_t cfgetispeed(const struct termios *termios_p) { return termios_p->c_ispeed; } + +#endif /* #if !defined(__BIONIC_) */
\ No newline at end of file diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/cfgetospeed.c b/native_client_sdk/src/libraries/nacl_io/syscalls/cfgetospeed.c index 1e6ccb7339..55eb2b5b63 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/cfgetospeed.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/cfgetospeed.c @@ -2,9 +2,19 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include <sys/types.h> +/* + * Include something that will define __BIONIC__, then wrap the entire file + * in this #if, so this file will be compiled on a non-bionic build. + */ + +#if !defined(__BIONIC__) + #include "nacl_io/kernel_intercept.h" #include "nacl_io/kernel_wrap.h" speed_t cfgetospeed(const struct termios *termios_p) { return termios_p->c_ospeed; } + +#endif /* #if !defined(__BIONIC_) */
\ No newline at end of file diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/cfsetispeed.c b/native_client_sdk/src/libraries/nacl_io/syscalls/cfsetispeed.c index 7ae776c9cc..1ebc379fa8 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/cfsetispeed.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/cfsetispeed.c @@ -2,6 +2,13 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include <sys/types.h> +/* + * Include something that will define __BIONIC__, then wrap the entire file + * in this #if, so this file will be compiled on a non-bionic build. + */ + +#if !defined(__BIONIC__) #include "nacl_io/kernel_intercept.h" #include "nacl_io/kernel_wrap.h" @@ -9,3 +16,5 @@ int cfsetispeed(struct termios *termios_p, speed_t speed) { termios_p->c_ispeed = speed; return 0; } + +#endif /* #if !defined(__BIONIC_) */
\ No newline at end of file diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/cfsetospeed.c b/native_client_sdk/src/libraries/nacl_io/syscalls/cfsetospeed.c index 7e13b1a781..ed7a678a9f 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/cfsetospeed.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/cfsetospeed.c @@ -2,6 +2,14 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include <sys/types.h> +/* + * Include something that will define __BIONIC__, then wrap the entire file + * in this #if, so this file will be compiled on a non-bionic build. + */ + +#if !defined(__BIONIC__) + #include "nacl_io/kernel_intercept.h" #include "nacl_io/kernel_wrap.h" @@ -9,3 +17,5 @@ int cfsetospeed(struct termios *termios_p, speed_t speed) { termios_p->c_ospeed = speed; return 0; } + +#endif /* #if !defined(__BIONIC_) */
\ No newline at end of file diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/cfsetspeed.c b/native_client_sdk/src/libraries/nacl_io/syscalls/cfsetspeed.c index 3d618e32ba..ecac8d71fc 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/cfsetspeed.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/cfsetspeed.c @@ -2,6 +2,14 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include <sys/types.h> +/* + * Include something that will define __BIONIC__, then wrap the entire file + * in this #if, so this file will be compiled on a non-bionic build. + */ + +#if !defined(__BIONIC__) + #include "nacl_io/kernel_intercept.h" #include "nacl_io/kernel_wrap.h" @@ -10,3 +18,5 @@ int cfsetspeed(struct termios *termios_p, speed_t speed) { termios_p->c_ospeed = speed; return 0; } + +#endif /* #if !defined(__BIONIC_) */
\ No newline at end of file diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/gai_strerror.c b/native_client_sdk/src/libraries/nacl_io/syscalls/gai_strerror.c index 458d3b91c3..265b1e0770 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/gai_strerror.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/gai_strerror.c @@ -8,7 +8,10 @@ #include <stdio.h> -#ifndef __GLIBC__ +#if !defined(__GLIBC__) +#if defined(__BIONIC__) +const +#endif char* gai_strerror(int errcode) { switch (errcode) { case EAI_BADFLAGS: return "Invalid value for `ai_flags' field."; diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/htonl.c b/native_client_sdk/src/libraries/nacl_io/syscalls/htonl.c index c29386f85c..d0f5f108f1 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/htonl.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/htonl.c @@ -4,7 +4,7 @@ #include "nacl_io/ossocket.h" -#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) +#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) && !defined(__BIONIC__) #include <string.h> @@ -20,4 +20,4 @@ inline uint32_t htonl(uint32_t hostlong) { return result; } -#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) */ +#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) ... */ diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/htons.c b/native_client_sdk/src/libraries/nacl_io/syscalls/htons.c index 0bdab70027..74e550c7c1 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/htons.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/htons.c @@ -4,7 +4,7 @@ #include "nacl_io/ossocket.h" -#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) +#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) && !defined(__BIONIC__) #include <string.h> @@ -18,4 +18,4 @@ inline uint16_t htons(uint16_t hostshort) { return result; } -#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) */ +#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) ... */ diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_aton.c b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_aton.c index 964587a9b1..7c4542b9d2 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_aton.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_aton.c @@ -6,6 +6,7 @@ #if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) +#include <stdio.h> #include <string.h> #include <limits.h> diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.c b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.c index 380cbc8791..4f78f21db4 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.c @@ -4,7 +4,7 @@ #include "nacl_io/ossocket.h" -#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) +#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) && !defined(__BIONIC__) static uint8_t GetByte(const void* addr, int byte) { const char* buf = (const char*)addr; @@ -19,4 +19,4 @@ char* inet_ntoa(struct in_addr in) { return addr; } -#endif // defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) +#endif // defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) ... diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc index e9bde2b133..5ee66d136a 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "nacl_io/ossocket.h" -#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) +#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) && !defined(__BIONIC__) #include <errno.h> #include <string.h> @@ -95,4 +95,4 @@ const char* inet_ntop(int af, const void* src, char* dst, socklen_t size) { EXTERN_C_END -#endif // defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) +#endif // defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) ... diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_pton.c b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_pton.c index 91d3c6cef5..3a74afdde4 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_pton.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_pton.c @@ -3,7 +3,7 @@ * found in the LICENSE file. */ #include "nacl_io/ossocket.h" -#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) +#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) && !defined(__BIONIC__) #include <ctype.h> #include <errno.h> @@ -144,4 +144,4 @@ int inet_pton(int af, const char *src, void *dst) { return -1; } -#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) */ +#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) ... */ diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/ioctl.c b/native_client_sdk/src/libraries/nacl_io/syscalls/ioctl.c index 3b7958a66f..10014b1bdc 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/ioctl.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/ioctl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013 The Chromium Authors. All rights reserved. +/* Copyright 2013 The Chromium Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -7,7 +7,13 @@ #include "nacl_io/kernel_intercept.h" #include "nacl_io/kernel_wrap.h" -int ioctl(int fd, unsigned long request, ...) { +#ifdef __BIONIC__ +#define REQ_TYPE int +#else +#define REQ_TYPE unsigned long +#endif + +int ioctl(int fd, REQ_TYPE request, ...) { va_list ap; va_start(ap, request); int rtn = ki_ioctl(fd, request, ap); diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/ntohl.c b/native_client_sdk/src/libraries/nacl_io/syscalls/ntohl.c index 8338a6a5dc..c7b6369c40 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/ntohl.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/ntohl.c @@ -4,7 +4,7 @@ #include "nacl_io/ossocket.h" -#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) +#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) && !defined(__BIONIC__) #include <string.h> @@ -18,4 +18,4 @@ inline uint32_t ntohl(uint32_t networklong) { ((uint32_t) input[3])); } -#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) */ +#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) ... */ diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/ntohs.c b/native_client_sdk/src/libraries/nacl_io/syscalls/ntohs.c index 19b6afe1bf..af0875930c 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/ntohs.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/ntohs.c @@ -4,7 +4,7 @@ #include "nacl_io/ossocket.h" -#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) +#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) && !defined(__BIONIC__) #include <string.h> @@ -16,4 +16,4 @@ inline uint16_t ntohs(uint16_t networkshort) { ((uint32_t) input[1])); } -#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) */ +#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) ... */ diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/poll.c b/native_client_sdk/src/libraries/nacl_io/syscalls/poll.c index b5ddff7892..f194528427 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/poll.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/poll.c @@ -1,10 +1,14 @@ -/* Copyright (c) 2013 The Chromium Authors. All rights reserved. +/* Copyright 2013 The Chromium Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "nacl_io/kernel_intercept.h" #include "nacl_io/kernel_wrap.h" +#if !defined(__BIONIC__) + int poll(struct pollfd *fds, nfds_t nfds, int timeout) { return ki_poll(fds, nfds, timeout); } + +#endif /* #if !defined(__BIONIC_) */
\ No newline at end of file diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/sigaddset.c b/native_client_sdk/src/libraries/nacl_io/syscalls/sigaddset.c index 3084cfd0d2..e3df654a62 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/sigaddset.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/sigaddset.c @@ -5,7 +5,7 @@ #include "nacl_io/kernel_intercept.h" #include "nacl_io/kernel_wrap.h" -#if defined(__native_client__) && !defined(__GLIBC__) +#if defined(__native_client__) && !defined(__GLIBC__) && !defined(__BIONIC__) int sigaddset(sigset_t* set, const int signum) { *set |= (1 << signum); return 0; diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/sigdelset.c b/native_client_sdk/src/libraries/nacl_io/syscalls/sigdelset.c index f17606c314..b595320fc9 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/sigdelset.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/sigdelset.c @@ -5,7 +5,7 @@ #include "nacl_io/kernel_intercept.h" #include "nacl_io/kernel_wrap.h" -#if defined(__native_client__) && !defined(__GLIBC__) +#if defined(__native_client__) && !defined(__GLIBC__) && !defined(__BIONIC__) int sigdelset(sigset_t* set, const int signum) { *set &= ~(1 << signum); return 0; diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/sigemptyset.c b/native_client_sdk/src/libraries/nacl_io/syscalls/sigemptyset.c index ad686c58ff..834509c1d9 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/sigemptyset.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/sigemptyset.c @@ -5,7 +5,7 @@ #include "nacl_io/kernel_intercept.h" #include "nacl_io/kernel_wrap.h" -#if defined(__native_client__) && !defined(__GLIBC__) +#if defined(__native_client__) && !defined(__GLIBC__) && !defined(__BIONIC__) int sigemptyset(sigset_t* set) { *set = 0; return 0; diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/sigfillset.c b/native_client_sdk/src/libraries/nacl_io/syscalls/sigfillset.c index f3ce939b13..0964ee681e 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/sigfillset.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/sigfillset.c @@ -5,7 +5,7 @@ #include "nacl_io/kernel_intercept.h" #include "nacl_io/kernel_wrap.h" -#if defined(__native_client__) && !defined(__GLIBC__) +#if defined(__native_client__) && !defined(__GLIBC__) && !defined(__BIONIC__) int sigfillset(sigset_t* set) { *set = ~0; return 0; diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/sigismember.c b/native_client_sdk/src/libraries/nacl_io/syscalls/sigismember.c index 6695eeb259..6a3218390d 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/sigismember.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/sigismember.c @@ -5,7 +5,7 @@ #include "nacl_io/kernel_intercept.h" #include "nacl_io/kernel_wrap.h" -#if defined(__native_client__) && !defined(__GLIBC__) +#if defined(__native_client__) && !defined(__GLIBC__) && !defined(__BIONIC__) int sigismember(const sigset_t* set, int signum) { return (*set & (1 << signum)) != 0; } diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/signal.c b/native_client_sdk/src/libraries/nacl_io/syscalls/signal.c index a111add893..c131e28f32 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/signal.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/signal.c @@ -5,6 +5,22 @@ #include "nacl_io/kernel_intercept.h" #include "nacl_io/kernel_wrap.h" +#if !defined(__BIONIC__) + sighandler_t signal(int signum, sighandler_t handler) { return ki_signal(signum, handler); } + +#else + +sighandler_t sysv_signal(int signum, sighandler_t handler) +{ + return ki_signal(signum, handler); +} + + +sighandler_t bsd_signal(int signum, sighandler_t handler) { + return ki_signal(signum, handler); +} + +#endif /* #if !defined(__BIONIC_) */
\ No newline at end of file diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/tcdrain.c b/native_client_sdk/src/libraries/nacl_io/syscalls/tcdrain.c index 49c078bb0c..866dfb4030 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/tcdrain.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/tcdrain.c @@ -2,6 +2,14 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include <sys/types.h> +/* + * Include something that will define __BIONIC__, then wrap the entire file + * in this #if, so this file will be compiled on a non-bionic build. + */ + +#if !defined(__BIONIC__) + #include <errno.h> #include "nacl_io/kernel_intercept.h" @@ -11,3 +19,5 @@ int tcdrain(int fd) { errno = ENOSYS; return -1; } + +#endif /* #if !defined(__BIONIC_) */
\ No newline at end of file diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/tcflow.c b/native_client_sdk/src/libraries/nacl_io/syscalls/tcflow.c index a29915351c..df3233b35e 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/tcflow.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/tcflow.c @@ -2,6 +2,13 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include <sys/types.h> +/* + * Include something that will define __BIONIC__, then wrap the entire file + * in this #if, so this file will be compiled on a non-bionic build. + */ + +#if !defined(__BIONIC__) #include <errno.h> #include "nacl_io/kernel_intercept.h" @@ -11,3 +18,5 @@ int tcflow(int fd, int action) { errno = ENOSYS; return -1; } + +#endif /* #if !defined(__BIONIC_) */
\ No newline at end of file diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/tcflush.c b/native_client_sdk/src/libraries/nacl_io/syscalls/tcflush.c index 5a59b8b694..85df5a734d 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/tcflush.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/tcflush.c @@ -1,6 +1,14 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +/* Copyright 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +#include <sys/types.h> +/* + * Include something that will define __BIONIC__, then wrap the entire file + * in this #if, so this file will be compiled on a non-bionic build. + */ + +#if !defined(__BIONIC__) #include "nacl_io/kernel_intercept.h" #include "nacl_io/ostermios.h" @@ -9,3 +17,4 @@ int tcflush(int fd, int queue_selector) { return ki_tcflush(fd, queue_selector); } +#endif /* #if !defined(__BIONIC_) */
\ No newline at end of file diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/tcgetattr.c b/native_client_sdk/src/libraries/nacl_io/syscalls/tcgetattr.c index 0715f45e19..8f0c7d02a5 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/tcgetattr.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/tcgetattr.c @@ -1,6 +1,15 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +/* Copyright 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +#include <sys/types.h> + +/* + * Include something that will define __BIONIC__, then wrap the entire file + * in this #if, so this file will be compiled on a non-bionic build. + */ + +#if !defined(__BIONIC__) #include "nacl_io/kernel_intercept.h" #include "nacl_io/ostermios.h" @@ -8,3 +17,5 @@ int tcgetattr(int fd, struct termios* termios_p) { return ki_tcgetattr(fd, termios_p); } + +#endif /* #if !defined(__BIONIC_) */
\ No newline at end of file diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/tcsendbreak.c b/native_client_sdk/src/libraries/nacl_io/syscalls/tcsendbreak.c index 967446745e..59d2294345 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/tcsendbreak.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/tcsendbreak.c @@ -2,6 +2,15 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include <sys/types.h> + +/* + * Include something that will define __BIONIC__, then wrap the entire file + * in this #if, so this file will be compiled on a non-bionic build. + */ + +#if !defined(__BIONIC__) + #include <errno.h> #include "nacl_io/kernel_intercept.h" @@ -11,3 +20,5 @@ int tcsendbreak(int fd, int duration) { errno = ENOSYS; return -1; } + +#endif /* #if !defined(__BIONIC_) */
\ No newline at end of file diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/tcsetattr.c b/native_client_sdk/src/libraries/nacl_io/syscalls/tcsetattr.c index bb443972c8..7d566b3139 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/tcsetattr.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/tcsetattr.c @@ -1,6 +1,14 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +/* Copyright 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +#include <sys/types.h> +/* + * Include something that will define __BIONIC__, then wrap the entire file + * in this #if, so this file will be compiled on a non-bionic build. + */ + +#if !defined(__BIONIC__) #include "nacl_io/kernel_intercept.h" #include "nacl_io/ostermios.h" @@ -8,3 +16,5 @@ int tcsetattr(int fd, int optional_actions, const struct termios* termios_p) { return ki_tcsetattr(fd, optional_actions, termios_p); } + +#endif /* #if !defined(__BIONIC_) */
\ No newline at end of file diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/uname.c b/native_client_sdk/src/libraries/nacl_io/syscalls/uname.c index 293b989ee4..19a822b14f 100644 --- a/native_client_sdk/src/libraries/nacl_io/syscalls/uname.c +++ b/native_client_sdk/src/libraries/nacl_io/syscalls/uname.c @@ -6,6 +6,10 @@ #include <string.h> #include <sys/utsname.h> +#if !defined(_UTSNAME_LENGTH) && defined(__BIONIC__) +#define _UTSNAME_LENGTH SYS_NMLN +#endif + int uname(struct utsname* buf) { memset(buf, 0, sizeof(struct utsname)); snprintf(buf->sysname, _UTSNAME_LENGTH, "NaCl"); diff --git a/native_client_sdk/src/libraries/ppapi_simple/library.dsc b/native_client_sdk/src/libraries/ppapi_simple/library.dsc index 0b2683df99..25eed71b08 100644 --- a/native_client_sdk/src/libraries/ppapi_simple/library.dsc +++ b/native_client_sdk/src/libraries/ppapi_simple/library.dsc @@ -1,5 +1,5 @@ { - 'TOOLS': ['newlib', 'glibc', 'pnacl', 'linux'], + 'TOOLS': ['bionic', 'newlib', 'glibc', 'pnacl', 'linux'], 'TARGETS': [ { 'NAME' : 'ppapi_simple', diff --git a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc b/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc index a9c7168e59..d9a1b7d846 100644 --- a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc +++ b/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc @@ -10,6 +10,7 @@ #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> +#include <termios.h> #include <algorithm> #include <cstdlib> diff --git a/native_client_sdk/src/tests/nacl_io_test/event_test.cc b/native_client_sdk/src/tests/nacl_io_test/event_test.cc index 76f5359619..8ca754da48 100644 --- a/native_client_sdk/src/tests/nacl_io_test/event_test.cc +++ b/native_client_sdk/src/tests/nacl_io_test/event_test.cc @@ -312,3 +312,38 @@ TEST_F(SelectPollTest, SelectMemPipe) { EXPECT_EQ(0, FD_ISSET(fds[1], &ex_set)); } +/** + * Test that calling select() only writes the initial parts of the fd_sets + * passed in. + * We had an issue when select() was calling FD_ZERO() on the incoming fd_sets + * which was causing corruption in ssh which always allocates the fd_sets to be + * hold 'nfds' worth of descriptors. + */ +TEST_F(SelectPollTest, SelectPartialFdset) { + int fds[2]; + + // Both FDs for regular files should be read/write but not exception. + fds[0] = kp->open("/test.txt", O_CREAT | O_WRONLY); + fds[1] = kp->open("/test.txt", O_RDONLY); + ASSERT_GT(fds[0], -1); + ASSERT_GT(fds[1], -1); + ASSERT_LT(fds[1], 8); + SetFDs(fds, 2); + + // Fill in all the remaining bytes in the fd_sets a constant value + static const char guard_value = 0xab; + for (int i = 1; i < sizeof(fd_set); i++) { + ((char*)&rd_set)[i] = guard_value; + ((char*)&wr_set)[i] = guard_value; + ((char*)&ex_set)[i] = guard_value; + } + + ASSERT_EQ(4, kp->select(fds[1] + 1, &rd_set, &wr_set, &ex_set, &tv)); + + // Verify guard values were not touched. + for (int i = 1; i < sizeof(fd_set); i++) { + ASSERT_EQ(guard_value, ((char*)&rd_set)[i]); + ASSERT_EQ(guard_value, ((char*)&wr_set)[i]); + ASSERT_EQ(guard_value, ((char*)&ex_set)[i]); + } +} diff --git a/native_client_sdk/src/tests/nacl_io_test/example.dsc b/native_client_sdk/src/tests/nacl_io_test/example.dsc index 48f7a54bf8..1a0c565ce1 100644 --- a/native_client_sdk/src/tests/nacl_io_test/example.dsc +++ b/native_client_sdk/src/tests/nacl_io_test/example.dsc @@ -1,5 +1,5 @@ { - 'TOOLS': ['newlib', 'glibc', 'pnacl', 'linux'], + 'TOOLS': ['bionic', 'newlib', 'glibc', 'pnacl', 'linux'], 'SEL_LDR': True, 'TARGETS': [ diff --git a/native_client_sdk/src/tests/nacl_io_test/kernel_wrap_test.cc b/native_client_sdk/src/tests/nacl_io_test/kernel_wrap_test.cc index dd8417f530..c043445af6 100644 --- a/native_client_sdk/src/tests/nacl_io_test/kernel_wrap_test.cc +++ b/native_client_sdk/src/tests/nacl_io_test/kernel_wrap_test.cc @@ -91,6 +91,7 @@ void MakeDummyStatbuf(struct stat* statbuf) { statbuf->st_ctime = 11; } +const mode_t kDummyMode = 0xbeef; const int kDummyInt = 0xdedbeef; const int kDummyInt2 = 0xcabba6e; const int kDummyInt3 = 0xf00ba4; @@ -151,9 +152,9 @@ TEST_F(KernelWrapTest, chdir) { } TEST_F(KernelWrapTest, chmod) { - EXPECT_CALL(mock, chmod(kDummyConstChar, kDummyInt)) + EXPECT_CALL(mock, chmod(kDummyConstChar, kDummyMode)) .WillOnce(Return(kDummyInt2)); - EXPECT_EQ(kDummyInt2, chmod(kDummyConstChar, kDummyInt)); + EXPECT_EQ(kDummyInt2,chmod(kDummyConstChar, kDummyMode)); } TEST_F(KernelWrapTest, chown) { @@ -195,11 +196,12 @@ TEST_F(KernelWrapTest, fchdir) { } TEST_F(KernelWrapTest, fchmod) { - EXPECT_CALL(mock, fchmod(kDummyInt, kDummyInt2)) .WillOnce(Return(-1)); - EXPECT_EQ(-1, fchmod(kDummyInt, kDummyInt2)); + EXPECT_CALL(mock, fchmod(kDummyInt, kDummyMode)) + .WillOnce(Return(-1)); + EXPECT_EQ(-1, fchmod(kDummyInt, kDummyMode)); - EXPECT_CALL(mock, fchmod(kDummyInt, kDummyInt2)) .WillOnce(Return(0)); - EXPECT_EQ(0, fchmod(kDummyInt, kDummyInt2)); + EXPECT_CALL(mock, fchmod(kDummyInt, kDummyMode)) .WillOnce(Return(0)); + EXPECT_EQ(0, fchmod(kDummyInt, kDummyMode)); } TEST_F(KernelWrapTest, fchown) { @@ -256,7 +258,7 @@ TEST_F(KernelWrapTest, getcwd) { } TEST_F(KernelWrapTest, getdents) { -#ifndef __GLIBC__ +#if !defined( __GLIBC__) && !defined(__BIONIC__) // TODO(sbc): Find a way to test the getdents wrapper under glibc. // It looks like the only way to exercise it is to call readdir(2). // There is an internal glibc function __getdents that will call the @@ -290,10 +292,20 @@ TEST_F(KernelWrapTest, ioctl) { EXPECT_EQ(kDummyInt3, ioctl(kDummyInt, kDummyInt2, buffer)); } +#if !defined(__BIONIC__) TEST_F(KernelWrapTest, isatty) { EXPECT_CALL(mock, isatty(kDummyInt)).WillOnce(Return(kDummyInt2)); EXPECT_EQ(kDummyInt2, isatty(kDummyInt)); + + // This test verifies that the IRT interception wrapper for isatty + // ignores the value of errno when isatty() returns 1. We had a bug + // where returning 1 from ki_isatty resulted in errno being returned + // by the IRT interface. + errno = kDummyInt3; + EXPECT_CALL(mock, isatty(kDummyInt)).WillOnce(Return(1)); + EXPECT_EQ(1, isatty(kDummyInt)); } +#endif TEST_F(KernelWrapTest, kill) { EXPECT_CALL(mock, kill(kDummyInt, kDummyInt2)).WillOnce(Return(kDummyInt3)); @@ -323,9 +335,9 @@ TEST_F(KernelWrapTest, mkdir) { EXPECT_CALL(mock, mkdir(kDummyConstChar, 0777)).WillOnce(Return(kDummyInt2)); EXPECT_EQ(kDummyInt2, mkdir(kDummyConstChar)); #else - EXPECT_CALL(mock, mkdir(kDummyConstChar, kDummyInt)) + EXPECT_CALL(mock, mkdir(kDummyConstChar, kDummyMode)) .WillOnce(Return(kDummyInt2)); - EXPECT_EQ(kDummyInt2, mkdir(kDummyConstChar, kDummyInt)); + EXPECT_EQ(kDummyInt2, mkdir(kDummyConstChar, kDummyMode)); #endif } @@ -381,13 +393,14 @@ TEST_F(KernelWrapTest, munmap) { TEST_F(KernelWrapTest, open) { - EXPECT_CALL(mock, open(kDummyConstChar, kDummyInt)) + // We pass O_RDONLY because we do not want an error in flags translation + EXPECT_CALL(mock, open(kDummyConstChar, 0)) .WillOnce(Return(kDummyInt2)); - EXPECT_EQ(kDummyInt2, open(kDummyConstChar, kDummyInt)); + EXPECT_EQ(kDummyInt2, open(kDummyConstChar, 0)); - EXPECT_CALL(mock, open(kDummyConstChar, kDummyInt)) + EXPECT_CALL(mock, open(kDummyConstChar, 0)) .WillOnce(Return(kDummyInt2)); - EXPECT_EQ(kDummyInt2, open(kDummyConstChar, kDummyInt)); + EXPECT_EQ(kDummyInt2, open(kDummyConstChar, 0)); } TEST_F(KernelWrapTest, pipe) { @@ -483,6 +496,7 @@ TEST_F(KernelWrapTest, symlink) { EXPECT_EQ(kDummyInt, symlink(kDummyConstChar, kDummyConstChar2)); } +#ifndef __BIONIC__ TEST_F(KernelWrapTest, tcflush) { EXPECT_CALL(mock, tcflush(kDummyInt, kDummyInt2)) .WillOnce(Return(kDummyInt3)); @@ -501,6 +515,7 @@ TEST_F(KernelWrapTest, tcsetattr) { .WillOnce(Return(kDummyInt3)); EXPECT_EQ(kDummyInt3, tcsetattr(kDummyInt, kDummyInt2, &term)); } +#endif TEST_F(KernelWrapTest, umount) { EXPECT_CALL(mock, umount(kDummyConstChar)).WillOnce(Return(kDummyInt)); @@ -515,6 +530,7 @@ TEST_F(KernelWrapTest, truncate) { EXPECT_EQ(0, truncate(kDummyConstChar, kDummyInt3)); } +#ifndef __BIONIC__ TEST_F(KernelWrapTest, lstat) { struct stat buf; EXPECT_CALL(mock, lstat(kDummyConstChar, &buf)).WillOnce(Return(-1)); @@ -523,6 +539,7 @@ TEST_F(KernelWrapTest, lstat) { EXPECT_CALL(mock, lstat(kDummyConstChar, &buf)).WillOnce(Return(0)); EXPECT_EQ(0, lstat(kDummyConstChar, &buf)); } +#endif TEST_F(KernelWrapTest, unlink) { EXPECT_CALL(mock, unlink(kDummyConstChar)).WillOnce(Return(kDummyInt)); @@ -547,7 +564,7 @@ TEST_F(KernelWrapTest, write) { EXPECT_EQ(kDummyInt3, write(kDummyInt, kDummyVoidPtr, kDummyInt2)); } -#ifdef PROVIDES_SOCKET_API +#if defined(PROVIDES_SOCKET_API) and !defined(__BIONIC__) TEST_F(KernelWrapTest, poll) { struct pollfd fds; EXPECT_CALL(mock, poll(&fds, kDummyInt, kDummyInt2)) @@ -650,12 +667,14 @@ TEST_F(KernelWrapTest, recvfrom) { recvfrom(kDummyInt, dummy_void_ptr, kDummyInt2, kDummyInt3, &addr, &len)); } +#ifndef __BIONIC__ TEST_F(KernelWrapTest, recvmsg) { struct msghdr msg; EXPECT_CALL(mock, recvmsg(kDummyInt, &msg, kDummyInt2)) .WillOnce(Return(kDummyInt3)); EXPECT_EQ(kDummyInt3, recvmsg(kDummyInt, &msg, kDummyInt2)); } +#endif TEST_F(KernelWrapTest, send) { EXPECT_CALL(mock, send(kDummyInt, kDummyVoidPtr, kDummySizeT, kDummyInt2)) diff --git a/native_client_sdk/src/tools/common.mk b/native_client_sdk/src/tools/common.mk index 75aaaadbb9..df2939d49f 100644 --- a/native_client_sdk/src/tools/common.mk +++ b/native_client_sdk/src/tools/common.mk @@ -14,9 +14,10 @@ # your project only builds in one or the other then this should be overridden # accordingly. # -ALL_TOOLCHAINS ?= pnacl newlib glibc ifneq ($(ENABLE_BIONIC),) -ALL_TOOLCHAINS += bionic +ALL_TOOLCHAINS ?= pnacl newlib glibc bionic +else +ALL_TOOLCHAINS ?= pnacl newlib glibc endif VALID_TOOLCHAINS ?= $(ALL_TOOLCHAINS) diff --git a/native_client_sdk/src/tools/create_nmf.py b/native_client_sdk/src/tools/create_nmf.py index dc821220b3..aa269dd0b3 100755 --- a/native_client_sdk/src/tools/create_nmf.py +++ b/native_client_sdk/src/tools/create_nmf.py @@ -528,6 +528,14 @@ def GetDefaultLibPath(config): 'ports/lib/glibc_x86_32/%s' % config, 'ports/lib/glibc_x86_64/%s' % config, ] + + bionic_dir = 'toolchain/%s_arm_bionic' % osname + if os.path.isdir(os.path.join(sdk_root, bionic_dir)): + libpath += [ + '%s/arm-nacl/lib' % bionic_dir, + '%s/arm-nacl/usr/lib' % bionic_dir, + 'lib/bionic_arm/%s' % config, + ] libpath = [os.path.normpath(p) for p in libpath] libpath = [os.path.join(sdk_root, p) for p in libpath] return libpath @@ -633,6 +641,8 @@ def main(argv): # Add default libraries paths to the end of the search path. config = options.debug_libs and 'Debug' or 'Release' options.lib_path += GetDefaultLibPath(config) + for path in options.lib_path: + Trace('libpath: %s' % path) pnacl_optlevel = None if options.pnacl_optlevel is not None: diff --git a/native_client_sdk/src/tools/lib/get_shared_deps.py b/native_client_sdk/src/tools/lib/get_shared_deps.py index 3287474080..99a5884bdd 100644 --- a/native_client_sdk/src/tools/lib/get_shared_deps.py +++ b/native_client_sdk/src/tools/lib/get_shared_deps.py @@ -39,6 +39,7 @@ OBJDUMP_ARCH_MAP = { 'elf64-x86-64-nacl': 'x86-64', 'elf32-x86-64-nacl': 'x86-64', 'elf32-i386-nacl': 'x86-32', + 'elf32-littlearm-nacl': 'arm', } # The proper name of the dynamic linker, as kept in the IRT. This is @@ -201,6 +202,17 @@ def _FindLibsInPath(name, lib_path): A list of system paths that match the given name within the lib_path''' files = [] for dirname in lib_path: + # The libc.so files in the the glibc toolchain is actually a linker + # script which references libc.so.<SHA1>. This means the lib.so itself + # does not end up in the NEEDED section for glibc. However with bionic + # the SONAME is actually libc.so. If we pass glibc's libc.so to objdump + # if fails to parse it, os this filters out libc.so expept for within + # the bionic toolchain. + # TODO(noelallen): Remove this once the SONAME in bionic is made to be + # unique in the same it is under glibc: + # https://code.google.com/p/nativeclient/issues/detail?id=3833 + if name == 'libc.so' and 'bionic' not in dirname: + continue filename = os.path.join(dirname, name) if os.path.exists(filename): files.append(filename) diff --git a/native_client_sdk/src/tools/lib/tests/get_shared_deps_test.py b/native_client_sdk/src/tools/lib/tests/get_shared_deps_test.py index d891c4fe58..a023c188b7 100755 --- a/native_client_sdk/src/tools/lib/tests/get_shared_deps_test.py +++ b/native_client_sdk/src/tools/lib/tests/get_shared_deps_test.py @@ -43,7 +43,8 @@ class TestGetNeeded(unittest.TestCase): def setUp(self): self.tempdir = None toolchain = os.path.join(CHROME_SRC, 'native_client', 'toolchain') - self.toolchain = os.path.join(toolchain, '%s_x86' % getos.GetPlatform()) + self.toolchain = os.path.join(toolchain, '%s_x86' % getos.GetPlatform(), + 'nacl_x86_glibc') self.objdump = os.path.join(self.toolchain, 'bin', 'i686-nacl-objdump') if os.name == 'nt': self.objdump += '.exe' diff --git a/native_client_sdk/src/tools/nacl_gcc.mk b/native_client_sdk/src/tools/nacl_gcc.mk index c5c1609601..ddd20d571a 100644 --- a/native_client_sdk/src/tools/nacl_gcc.mk +++ b/native_client_sdk/src/tools/nacl_gcc.mk @@ -43,11 +43,17 @@ NCVAL ?= python $(NACL_SDK_ROOT)/tools/ncval.py # Architecture-specific flags X86_32_CFLAGS ?= X86_64_CFLAGS ?= -ARM_CFLAGS ?= - X86_32_CXXFLAGS ?= X86_64_CXXFLAGS ?= + +# Use DWARF v3 which is more commonly available when debugging +ifeq ($(CONFIG),Debug) +ARM_CFLAGS ?= -gdwarf-3 +ARM_CXXFLAGS ?= -gdwarf-3 +else +ARM_CFLAGS ?= ARM_CXXFLAGS ?= +endif X86_32_LDFLAGS ?= -Wl,-Map,$(OUTDIR)/$(TARGET)_x86_32.map X86_64_LDFLAGS ?= -Wl,-Map,$(OUTDIR)/$(TARGET)_x86_64.map @@ -329,7 +335,7 @@ endif ifneq (,$(findstring arm,$(ARCHES))) all: $(OUTDIR)/$(1)_arm.nexe $(OUTDIR)/$(1)_arm.nexe: $(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_arm)) $(foreach dep,$(4),$(STAMPDIR)/$(dep).stamp) - $(call LOG,LINK,$$@,$(ARM_LINK) -o $$@ $$(filter %.o,$$^) $(NACL_LDFLAGS) $(ARM_LDFLAGS) $(foreach path,$(6),-L$(path)/$(TOOLCHAIN)_arm/$(CONFIG)) $(foreach lib,$(3),-l$(lib)) $(5)) + $(call LOG,LINK,$$@,$(ARM_LINK) -static -o $$@ $$(filter %.o,$$^) $(NACL_LDFLAGS) $(ARM_LDFLAGS) $(foreach path,$(6),-L$(path)/$(TOOLCHAIN)_arm/$(CONFIG)) $(foreach lib,$(3),-l$(lib)) $(5)) $(call LOG,VALIDATE,$$@,$(NCVAL) $$@) endif endef diff --git a/native_client_sdk/src/tools/tests/create_nmf_test.py b/native_client_sdk/src/tools/tests/create_nmf_test.py index aca8fe9723..da09dd20d0 100755 --- a/native_client_sdk/src/tools/tests/create_nmf_test.py +++ b/native_client_sdk/src/tools/tests/create_nmf_test.py @@ -84,7 +84,8 @@ class TestNmfUtils(unittest.TestCase): def setUp(self): self.tempdir = None toolchain = os.path.join(CHROME_SRC, 'native_client', 'toolchain') - self.toolchain = os.path.join(toolchain, '%s_x86' % getos.GetPlatform()) + self.toolchain = os.path.join(toolchain, '%s_x86' % getos.GetPlatform(), + 'nacl_x86_glibc') self.objdump = os.path.join(self.toolchain, 'bin', 'i686-nacl-objdump') if os.name == 'nt': self.objdump += '.exe' |