aboutsummaryrefslogtreecommitdiffstats
path: root/exec/exec.c
diff options
context:
space:
mode:
authorPo Lu2023-08-07 08:51:11 +0800
committerPo Lu2023-08-07 08:51:11 +0800
commitc71a520d1da636a722cf87b46534ca3b5aafbc7b (patch)
tree95a3099c065800f60602e0a403b551a6d6dba139 /exec/exec.c
parent18e7bc87521e3c48b819cfe4a113f532ba905561 (diff)
parent9a9f73041d09d2da7ed562c7ffae0d9519562fba (diff)
downloademacs-c71a520d1da636a722cf87b46534ca3b5aafbc7b.tar.gz
emacs-c71a520d1da636a722cf87b46534ca3b5aafbc7b.zip
Introduce an Android window system port for GNU Emacs
* src/xterm.h: New fields `quit_keysym' and `quit_keysym_time'. * src/xterm.c (handle_one_xevent): Check for the quit keysym, and set Vquit_flag upon witnessing two clicks in rapid succession. (x_term_init): Set `quit_keysym'. (init_xterm): Fix typo in name of `register_textconv_interface'. (syms_of_xterm) <Vx_toolkit_scroll_bars>: Describe its default value on android. * src/xfns.c (xic_string_conversion_callback): Pass `0' as the last argument to textconv_query. (Fx_server_vendor, Fx_server_version): Document return values on Android. * src/xfaces.c (Fx_family_fonts, set_lface_from_font): Use FRAME_RES instead of FRAME_RES_Y, respecting user preferences on window systems that have distinct display and font scaling factors. (Fx_load_color_file): Call `emacs_fclose', not fclose. * src/xdisp.c (tab_bar_item_info): Allow `close_p' to be NULL. (get_tab_bar_item): Update commentary to reflect that change. (get_tab_bar_item_kbd): New function, resembling get_tab_bar_item. (build_desired_tool_bar_string): Clear `f->tool_bar_wraps_p'; insert new line characters if a QCwrap item is encountered, and set f->tool_bar_wrap_p. Replace characters beyond the end of the tool bar with spaces. (display_tool_bar_line): Move iterator to the next line if in contact with an explicit line-wrap item. (redisplay_internal): If there are newline characters in the tool bar, refrain from coercing each row into being identically tall. Don't call `set_tty_color_mode' on Android. (mark_window_display_accurate_1): Report changes to the point and mark to input methods. (display_menu_bar): Adjust ifdefs to allow non-X window systems to use the built-in menu bar. (draw_row_with_mouse_face): Don't call TTY functions on Android. (note_mouse_highlight): Call `popup_activated' on Android. (expose_frame): Correctly work on the menu bar window. (gui_union_rectangles): New function. * src/window.h (struct window): New fields for recording the last window and point positions, along with an ephemeral position used during IM text conversion. (WINDOW_MENU_BAR_P): Correct definition for non-X window systems without external menu bars. * src/window.c (replace_buffer_in_windows): Call Qreplace_buffer_in_windows only when bound. * src/w32proc.c (sys_spawnve): Pass extra argument to openp. * src/w32font.c (fill_in_logfont): Use font scaling factor, not the display scaling factor. * src/w32.c (check_windows_init_file): Pass extra argument to openp. * src/verbose.mk.in (AM_V_JAVAC, AM_V_DX, AM_V_AAPT) (AM_V_ZIPALIGN, AM_V_SILENT): New variables. * src/textconv.h (struct textconv_interface): New `point_changed', `compose_region_changed' and `notify_conversion'. Add declarations for new functions. * src/textconv.c (TEXTCONV_DEBUG): New macro. (suppress_conversion_count): New variable. (enum textconv_batch_edit_flags): New flag. (copy_buffer): Don't overwrite text before the gap with the text after. (get_mark, select_window): New functions. (textconv_query): New argument FLAGS. Contingent upon its value, use the previous point or mark or skip the conversion region. (sync_overlay, record_buffer_change, reset_frame_state) (detect_conversion_events, restore_selected_window) (really_commit_text, really_finish_composing_text) (really_set_composing_region, really_delete_composing_text) (really_request_point_update, really_set_point_and_mark) (complete_edit): New functions. (struct complete_edit_check_context): New structure; store in it the result of editing operations. (complete_edit_check, handle_pending_conversion_events_1) (decrement_inside, handle_pending_conversion_events) (start_batch_edit, end_batch_edit, commit_text) (set_composing_text, textconv_set_point_and_mark) (request_point_update, textconv_barrier, get_extracted_text) (get_surrounding_text, conversion_disabled_p) (report_selected_window_change, report_point_change) (disable_text_conversion, resume_text_conversion) (register_textconv_interface, check_postponed_buffers) (postponed_buffers, Fset_text_conversion_style) (syms_of_textconv) <Qaction, Qtext_conversion, Qpush_mark, Qunderline, Qoverriding_text_conversion_style, Vtext_conversion_edits, Voverriding_text_conversion_style, Vtext_conversion_face>: New functions, symbols and variables. * src/terminal.c (Fterminal_live_p): Return Qandroid if type is output_android. * src/termhooks.h (enum output_method): Add `output_android'. (struct terminal) <display_info>: Add union constituent field for `android'. <query_colors>: Define on Android as well. (TERMINAL_FONT_CACHE) [HAVE_ANDROID]: Return the inappropriately named font cache field on Android. * src/term.c (string_cost, string_cost_one_line, per_line_cost) (calculate_costs, produce_glyphs, produce_glyphs, tty_capable_p) (tty_capable_p, device, init_tty, maybe_fatal) (delete_tty) [HAVE_ANDROID]: Exclude or turn these functions into vestiges. (Fsuspend_tty, Fresume_tty): Call `emacs_fclose' and always signal on Android. (Fresume_tty): Call `emacs_fdopen'. (Ftty__set_output_buffer_size) [HAVE_ANDROID]: Remove this function. (encode_terminal_code): Replace with a stub. (init_tty, delete_tty, maybe_fatal): Call `emacs_fclose'. (syms_of_term): Remove most unnecessary code on Android. <system_uses_terminfo>: Always set this option on Android. * src/sysdep.c (init_standard_fds): Call emacs_fopen. (reset_sigio, widen_foreground_group): Define out on Android. (reset_sys_modes): Don't call either function on Android. (init_sigbus, handle_sigbus): New functions. (init_signals): Don't add user signals on Android. Register signal handlers for SIGBUS, and refrain from handling SIGSEGV. (emacs_fstatat): Wrap android_fstatat on Android. (sys_fstat, sys_faccessat): New function. (emacs_openat): Exclude this function when building libemacs.so. (emacs_open, emacs_open_noquit, emacs_fopen, emacs_close): Wrap functions defined in the Android filesystem emulation code. (emacs_fdopen, emacs_fclose, emacs_unlink, emacs_symlink) (emacs_rmdir, emacs_mkdir, emacs_renameat_noreplace, emacs_rename) (emacs_fchmodat): New wrappers for more of those functions. (close_output_streams): Placate the file descriptor sanitizer that's included with android. * src/sound.c (Fplay_sound_internal): Pass extra argument to openp. * src/sfntfont.h: * src/sfntfont.c: * src/sfntfont-android.c: * src/sfnt.h: * src/sfnt.c: New files. * src/scroll.c: Exclude the entire file on Android. * src/process.c: (allocate_pty): Call sys_faccessat, not faccessat. (Fmake_process): Call openp with an extra argument. (wait_reading_process_output): Call android_select. (Fprocess_send_eof): Don't call tcdrain if not present. (handle_child_signal): Write a comment describing a small, seldom encountered issue. * src/print.c (print_vectorlike): Don't print FONT_EXTRA_INDEX for font entities. * src/pdumper.c (Fdump_emacs_portable): Allow dumping in interactive Emacs's on Android, as this is performed within loadup.el. (dump_discard_mem): Use madvise if posix_advise is not present. (pdumper_load): Call sys_fstat, not fstat. (syms_of_pdumper) <Vpdumper_fingerprint>: Calculate the fingerprint for this Emacs executable and store it there. * src/menu.c (have_boxes): Android has boxes. (push_submenu_start, push_submenu_end): Define on Android. (single_menu_item): Produce submenus on Android as well. (x_popup_menu_1): Call EVENT_START, in contrast to duplicating its old functionality with calls to Fcar and XCDR. (Fx_popup_menu): Update documentation to reflect that touch screen events are now accepted as POSITION. * src/marker.c (set_marker_internal): Redisplay buffers when their mark changes, enabling changes to be reported to the IME. * src/lread.c (lread_fd, lread_fd_cmp, lread_fd_p, lread_close) (lread_fstat, lread_read_quit, lread_lseek, file_stream) (file_seek, file_stream_valid_p, file_stream_close) (file_stream_invalid, getc): New macros. Define to an implementation with file descriptors and file streams on systems other than Android 2.3+, and one using Android file descriptors on those systems. (USE_ANDROID_ASSETS): Define on Android 2.3+; (file_get_char): New function. (infile, skip_dyn_bytes, skip_dyn_eof, readbyte_from_stdio) (read_filtered_event, safe_to_load_version, close_infile_unwind): Implement in terms of those macros. (close_file_unwind_android_fd): New function. (Fload): Pass extra argument to `openp' and use Android file descriptors where possible. (Flocate_file_internal): Pass extra argument to `openp'. (maybe_swap_for_eln1): Call sys_fstat, not fstat. (openp): New arg PLATFORM; if supplied and opening a platform-specific file descriptor replacement is possible, place one there. (build_load_history): Fix typos in comments. (skip_lazy_string): Implement in terms of the aformentioned macros. * src/lisp.h: Add declarations for new functions. * src/keyboard.h (reading_key_sequence): Declare here. (EVENT_START): Treat touch screen events specially by returning the posn of their touch point. * src/keyboard.c (reading_key_sequence, menu_bar_touch_id): New variables. (command_loop_1): (read_menu_command): Pass false to read_key_sequence. (read_char): Update commentary. (readable_events): If text conversion events (edits from an input method) are queued, return 1. (kbd_buffer_get_event): If text conversion events exist, carry out the edits contained within. Then, generate a Qtext_conversion event. (lispy_function_keys, FUNCTION_KEY_OFFSET): Define function key array on Android. (coords_in_tab_bar_window): New function. (make_lispy_event) <TOUCHSCREEN_BEGIN_EVENT>: Keep track of touches that fall into the confines of the tab bar, and include the tab bar item in their position lists. Moreover, retain and track the touch in C code if it's taking place within the menu bar. <TOUCHSCREEN_END_EVENT>: Likewise for the tab bar; generate menu bar events if the touch ends on a menu item and was previously singled out for tracking. <TOUCHSCREEN_UPDATE_EVENT>: Don't deliver this event if the frame is dead, or if it was identified for tracking since the only touch sequence that changed begun inside the menu bar. (handle_async_input): Call android_check_query_urgent. (handle_input_available_signal): Add memory fence. (parse_tool_bar_item): Handle `wrap' properties within tool bar items moving subsequent items onto a new row. (access_keymap_keyremap): New arguments START, END, KEYBUF. Set Qcurrent_key_remap_sequence around calls to the remap function. (keyremap_step): Pass the necessary information to access_keymap_keyremap. (restore_reading_key_sequence): New function. (read_key_sequence): Set `reading_key_sequence'. New arg DISABLE_TEXT_CONVERSION_P, which causes text conversion to be disabled as long as the key sequence is being read. Disable text conversion as well if a menu or function key prefix is read, insert imaginary prefix keys before touchscreen events within special areas of a frame. Don't insert prefix keys if input is being mocked, which transpires if the input is in actuality originating from a key translation map. (read_key_sequence_vs): New argument DISABLE_TEXT_CONVERSION. (Fread_key_sequence): New argument DISABLE_TEXT_CONVERSION. (Fopen_dribble_file): Use emacs_fclose. (head_table): Make touchscreen-begin and touchscreen-end events touchscreen events. (syms_of_keyboard) <QCwrap, Qtouchscreen, Qtext_conversion>: New symbols. <disable_inhibit_text_conversion, Vcurrent_key_remap_sequence>: New variables. * src/inotify.c (Finotify_add_watch): Detect and avoid watching special files that don't exist from the POV of inotify. * src/image.c (image_create_bitmap_from_data) (image_create_bitmap_from_file, free_bitmap_record) (prepare_image_for_display, image_clear_image_1) (image_clear_image_1, image_size_in_bytes, image_set_transform): (Create_Pixmap_From_Bitmap_Data, lookup_rgb_color) (image_to_emacs_colors, image_from_emacs_colors) (image_pixmap_draw_cross, image_disable_image): Implement on Android, reusing much of the X11 code. (matrix_identity, matrix_rotate, matrix_mirror_horizontal) (matrix_translate): New functions. (x_check_image_size, x_create_x_image_and_pixmap) (x_destroy_x_image, image_check_image_size) (image_create_x_image_and_pixmap_1, image_destroy_x_image) (gui_put_x_image, image_get_x_image, image_unget_x_image): Implement on Android. (image_find_image_fd): Return an Android file descriptor if possible. (close_android_fd): New function. (slurp_file): Accept `image_fds', defined to Android file descriptors. (xpm_load): Enable built-in XPM support on Android. (xbm_load, pbm_load, png_load_body, jpeg_load_body, gif_load) (webp_load, imagemagick_load_image, svg_load): Use image file descriptors on Android; these file descriptors may in fact represent compressed asset streams, and obviate the necessity of creating a new file descriptor for each asset image opened. (Fimage_transforms_p): Report rotate90 on Android. (image_types, syms_of_image): Enable built-in XPM support on Android. * src/fringe.c (init_fringe_bitmap): Bit swap bitmaps on Android, as on X. * src/frame.h (enum text_conversion_operation): New enumerator. (struct text_conversion_action, struct text_conversion_state): New variable. (struct frame): New fields `tool_bar_wraps_p' and `conversion'. Increase the width of `output_method'. <output_data>: Add `android' field. <wait_event_type>: Define on Android as well. (fset_menu_bar_window): Define correctly, so that it's declared on non-X builds without external menu bars. (FRAME_ANDROID_P): Define macro. (FRAME_WINDOW_P) [HAVE_ANDROID]: Define to FRAME_ANDROID_P. (FRAME_RES): New macro. (MOUSE_HL_INFO): Define without referencing tty output data on Android, which doesn't have them. * src/frame.c (Fframep): Return `android' on Android systems. (Fwindow_system): Likewise. (make_frame): Clear text conversion state and `tool_bar_wraps_p'. (Fmake_terminal_frame): Signal that Android doesn't support text terminals. (delete_frame): Reset text conversion state prior to deleting the frame. (gui_display_get_resource): Don't call the resource hook on Android. (Fx_parse_geometry): Pacify compiler warning. (make_monitor_attribute_list): Don't always use SOURCE if nil. (syms_of_frame) <Qandroid>: New symbol. <Vdefault_frame_scroll_bars>: Don't default scroll bars to an enabled state on Android. * src/fontset.c (fontset_find_font): Tackle an unusual problem. * src/font.h (struct font_entity): New field `is_android'. (PT_PER_INCH): Define to 160.00 on Android. * src/font.c (font_make_entity): New function. (font_make_entity_android): New variant that sets `is_android' to true. (font_pixel_size, font_find_for_lface, font_open_for_lface) (Ffont_face_attributes, Fopen_font): Respect the distinction between frame text and display scales. * src/fns.c (Flocale_info): Silence compiler warning. * src/filelock.c (BOOT_TIME): Undefine BOOT_TIME when building libemacs.so (get_boot_time, rename_lock_file, create_lock_file) (current_lock_owner, make_lock_file_name, unlock_file): Employ wrappers for Android filesystem operations. * src/fileio.c (emacs_fd, emacs_fd_open, emacs_fd_close) (emacs_fd_read, emacs_fd_lseek, emacs_fd_fstat, emacs_fd_valid_p): New type and macros; define them to suitable values, akin to those in lread.c (check_vfs_filename): New function. (file_access_p): Call `sys_faccessat'. (close_file_unwind_emacs_fd): New function. (fclose_unwind): Call `emacs_fclose', not fclose. (file_name_directory): Export this function. (user_homedir): If PW->pw_dir is not set and its uid is the current user, call `android_get_home_directory'. (get_homedir): Call `android_get_home_directory' if PW->pw_dir is not set. (Fcopy_file, Fmake_directory_internal, Fdelete_directory_internal) (Fdelete_file, Frename_file, Fmake_symbolic_link, Faccess_file) (file_directory_p, file_accessible_directory_p, Fset_file_modes) (Fset_file_times, Ffile_newer_than_file_p, read_non_regular) (Finsert_file_contents, write_region) (Fverify_visited_file_modtime, Fset_visited_file_modtime) (do_auto_save_unwind): Make use of Android filesystem wrappers and file descriptors where possible. (Fadd_name_to_file): Prohibit creating links to and from files residing on Android special directories. (Ffile_system_info): Avoid compilation failure on Android, where Gnulib can't find out how to implement statfs. * src/epaths.in [HAVE_ANDROID && !ANDROID_STUBIFY]: Deface this file, so Makefile cannot change the hard-coded values within. * src/emacs.c (using_utf8): Correctly initialize mbstate_t on Android. (init_cmdargs): Pass extra argument to openp. (load_pdump): When building libemacs.so, use solely the file provided on the command line or as an argument to `android_emacs_init'. (load_seccomp): Call sys_fstat, not fstat. (main, android_emacs_init): Name `main' `android_emacs_init' when building libemacs.so, and accept an argument designating the dump file. (main): Initialize text conversion and Android. Don't presume that argv is NULL terminated. (Fkill_emacs, shut_down_emacs): Properly implement RESTART on Android. (syms_of_emacs) <Vsystem_type>: Describe the possible value `android'. * src/emacs-module.c (MODULE_HANDLE_NONLOCAL_EXIT): Cease relying on GCC clean-up attribute extension. (MODULE_INTERNAL_CLEANUP): New macro. (module_make_global_ref, module_free_global_ref) (module_make_function, module_get_function_finalizer) (module_make_interactive, module_funcall, module_extract_integer) (module_extract_float, module_copy_string_contents) (module_get_user_ptr, module_set_user_ptr) (module_get_user_finalizer, module_set_user_finalizer) (module_vec_set, module_vec_size, module_process_input) (module_extract_big_integer, module_make_big_integer): Carry out necessary clean-up tasks using MODULE_HANDLE_NONLOCAL_EXIT. * src/editfns.c (Fuser_full_name): Call `android_user_full_name', as USER_FULL_NAME doesn't always work. * src/doc.c (doc_fd, doc_fd_p, doc_open, doc_read_quit) (doc_lseek): New types and macros, resembling those in lread.c. (get_doc_string, Fsnarf_documentation): Implement in terms of those macros, so as to use Android asset streams directly. * src/dispnew.c (clear_current_matrices, clear_desired_matrices) (allocate_matrices_for_window_redisplay, free_glyphs) (redraw_frame, update_frame, scrolling, update_frame_line): Disable support for text terminals when building for Android. (Fopen_termscript): Use emacs_fclose. (init_display_interactive): Set Vinitial_window_system to Qandroid, and lose if Emacs needs to create a text terminal. * src/dispextern.h (No_Cursor, Emacs_Rectangle, struct gui_box): New definitions. (struct glyph_string) <gc>: Define to the Android GC type. (HAVE_NATIVE_TRANSPHORMS): Define on Android. (struct image): New fields `ximg', `mask_img', as on X. (enum tool_bar_item_idx): New tool bar item property TOOL_BAR_ITEM_WRAP. * src/dired.c (emacs_dir, emacs_closedir, emacs_readdir): New typedef and definitions. (open_directory): Return emacs_dir; use android_opendir on Android, instead of at-funcs. (directory_files_internal_unwind): Call emacs_closedir. (read_dirent): Call emacs_readdir. (directory_files_internal, file_name_completion) (file_name_completion_dirp): Use Android wrappers for directories and files. (file_attributes): Abstain from openat on Android. * src/conf_post.h (MB_CUR_MAX): Define to REPLACEMENT_MB_CUR_MAX if necessary to counteract inept LLVM headers. * src/coding.h (from_unicode_buffer): Define if HAVE_ANDROID as well. * src/coding.c (from_unicode_buffer): Define on Android, creating a variant that understands UCS-16 extended into wchar_t. (syms_of_coding) <Qutf_16le>: Define on Android. * src/charset.c (load_charset_map_from_file): Supply extra argument to openp, and call Emacs wrappers for fdopen and fclose. * src/callproc.c (get_current_directory): Return the home directory if ENCODED is a special directory. (delete_temp_file): Call emacs_unlink in lieu of unlink. (call_process): Use openp. (emacs_spawn): Use Android executable loader binary if needed and enabled. (init_callproc): Set Vshell_file_name to /system/bin/sh if libemacs.so. (syms_of_callproc) <Vctags_program_name, Vetags_program_name, Vhexl_program_name, Vemacsclient_program_name, Vmovemail_program_name>: New variables. Define to the names of the programs they respectively stand for. * src/callint.c (Fcall_interactively): Supply new argument in calls to Fread_key_sequence and Fread_key_sequence_vector. * src/buffer.h (struct buffer) <text_conversion_style_>: New bvar. (bset_text_conversion_style): New bvar setter. * src/buffer.c (init_buffer_once): Set the text conversion style. (syms_of_buffer) <BVAR (current_buffer, text_conversion_style)>: Define new BLV. * src/androidvfs.c: * src/androidterm.h: * src/androidterm.c: * src/androidselect.c: * src/androidmenu.c: * src/androidgui.h: * src/androidfont.c: * src/androidfns.c: * src/android.h: * src/android.c: * src/android-emacs.c: * src/android-asset.h: New function. * src/alloc.c (cleanup_vector): Finalize Android font entities. (find_string_data_in_pure) [__i386__ && !__clang__]: On Android, compensate for a bug in the latest NDK GCC. (mark_pinned_symbols, android_make_lisp_symbol): Elude another bug in debuginfo generation with an almost nonsensical fix. (garbage_collect): Mark androidterm and sfntfont. (mark_frame): Mark text conversion actions and info. * src/Makefile.in (XCONFIGURE): New variable. If set, add srcdir to vpath. (hostlib): New variable, always defined to libgnu.a on the build machine. (GIF_CFLAGS, JPEG_CFLAGS, TIFF_CFLAGS, SQLITE3_CFLAGS) (LIBSELINUX_CFLAGS, ANDROID_OBJ, ANDROID_LIBS, ANDROID_LDFLAGS) (ANDROID_BUILD_CFLAGS, LIBGMP_CFLAGS): New variables. (CM_OBJ): Update commentary. (EMACS_CFLAGS): Add new compiler flags variables. (base_obj): Add ANDROID_OBJ. (SOME_MACHINE_OBJECTS): Add Android-related objects. (lisp.mk): Generate from its absolute file name. ($(lispsource)/international/charprop.el): Don't generate when building libemacs.so. ($(libsrc)/make-docfile$(EXEEXT) $(libsrc)/make-fingerprint$(EXEEXT)): Depend on libgnu.a on the build machine. (mostlyclean): Remove libemacs.so. (build-counter.c, libemacs.so, android-emacs): New targets. These targets are made from this Makefile copied to a subdirectory of `cross', and provide the Emacs library and an ancillary binary used by the Android port. * nt/mingw-cfg.site: * nt/gnulib-cfg.mk: Impede building Gnulib's vasnprintf* code. * msdos/sedlibmk.inp: * msdos/sedlibcf.inp: * msdos/sed3v2.inp: * msdos/sed1v2.inp: Fix the DJGPP build. * make-dist (possibly_non_vc_files): Add exec/configure and exec/config.h.in. * m4/ndk-build.m4: New file. * m4/getline.m4: * m4/getdelim.m4: * m4/asm-underscore.m4: Update from Gnulib. * lisp/wid-edit.el (widget-event-point): Treat touch screen events correctly. (widget-keymap): Map touchscreen-begin to widget-button-click. (widget-event-start): New function. (widget-button--check-and-call-button): (widget-button-click): Behave correctly when confronted by touch screen events. * lisp/version.el (android-read-build-system) (android_read_build_time): New functions. (emacs-build-system, emacs-repository-version-android) (emacs-repository-get-version): (emacs-repository-get-branch): Implement properly on Android, by reading a file generated during the packaging process. * lisp/touch-screen.el: New file, supplying support for translating raw touch screen events into gestures. * lisp/tool-bar.el (secondary-tool-bar-map): New defvar. (tool-bar--cache-key, tool-bar--secondary-cache-key): Make defsubsts. (tool-bar--flush-key): Flush caches for the secondary tool bar as well. (tool-bar-make-keymap, tool-bar-make-keymap-1): Append the secondary tool bar map below the primary tool bar map. (modifier-bar-modifier-list): New variable. (tool-bar-apply-modifiers, modifier-bar-button) (tool-bar-event-apply-alt-modifier) (tool-bar-event-apply-super-modifier) (tool-bar-event-apply-hyper-modifier) (tool-bar-event-apply-shift-modifier) (tool-bar-event-apply-control-modifier) (tool-bar-event-apply-meta-modifier, modifier-bar-available-p) (modifier-bar-mode): New functions. * lisp/textmodes/text-mode.el (text-mode): Set text-conversion-style to t. * lisp/textmodes/reftex-global.el (reftex-create-tags-file): Use etags-program-name to provide the name of the etags program. * lisp/textmodes/conf-mode.el (conf-mode-initialize): Enable text conversion. * lisp/textmodes/artist.el (artist-figlet-get-font-list): Use /system/bin/sh on Android. * lisp/term/android-win.el: New file. * lisp/term.el (term-mode): Always display the on screen keyboard. (term-exec-1): Use /system/bin/sh on Android. * lisp/tab-line.el (tab-line-tab-map) (tab-line-new-tab) (tab-line-select-tab) (tab-line-close-tab) (tab-line-track-tap) (tab-line-event-start): Improve support for touch screen events. * lisp/tab-bar.el (tab-bar-mouse-context-menu): (tab-bar-map): Likewise. (tab-bar-handle-timeout, tab-bar-touchscreen-begin): New functions. * lisp/subr.el (event-start): Don't return nonsense if EVENT is a touchscreen event. (event-end): Likewise. (read-key): Disable text conversion within read-key-sequence-vector. (read-char-choice-with-read-key): Display the on screen keyboard. (read-char-from-minibuffer): Disable text conversion. (use-dialog-box-p): Prefer dialog boxes on Android. (y-or-n-p): Disable text conversion properly under all three modes of operation. * lisp/startup.el (android-fonts-enumerated): New variable. (normal-top-level): Load system fonts on Android. * lisp/speedbar.el (speedbar-fetch-etags-command): Use etags-program-name instead of hard-coding `etags'. * lisp/simple.el (normal-erase-is-backspace-setup-frame): Return true on Android. (event-apply-modifier): Correctly apply Shift and Control modifiers to keys with other modifiers. (undo-auto-amalgamate): Mention analyze-text-conversion wrt being an amalgamating command. * lisp/shell.el (shell--command-completion-data): Don't lose if PATH contains an inaccessible directory. * lisp/progmodes/prog-mode.el (prog-mode): Enable text conversion. * lisp/progmodes/cperl-mode.el (cperl-etags): Don't hard-code etags, employ etags-program-name instead. * lisp/progmodes/cc-mode.el (c-initialize-cc-mode): Initialize text conversion hook. * lisp/progmodes/cc-cmds.el (c-post-text-conversion): New function. Do electric characters. * lisp/play/gamegrid.el (gamegrid-setup-default-font): Don't crash if the display resolution is too high. * lisp/play/dunnet.el (text-conversion-style): * lisp/play/doctor.el (doctor-mode): Enable text conversion. * lisp/pixel-scroll.el (pixel-scroll-precision-scroll-down-page) (pixel-scroll-precision-scroll-Up-page): Make autoloads. * lisp/org/org-ctags.el (org-ctags-path-to-ctags): Use ctags-program-name, not ctags. * lisp/obsolete/terminal.el (terminal-emulator): Start /system/bin/sh, not /bin/sh. * lisp/net/tramp.el (tramp-encoding-shell): Use /system/bin/sh on Android. * lisp/net/eww.el (eww-form-submit, eww-form-file) (eww-form-checkbox, eww-form-select): Define these faces on Android as well. * lisp/net/browse-url.el (browse-url-default-browser) (browse-url--browser-defcustom-type): Specify on Android. (browse-url-android-share, browse-url-default-android-browser): New option and function. * lisp/mwheel.el (mouse-wheel-down-event, mouse-wheel-up-event) (mouse-wheel-left-event, mouse-wheel-right-event): Define suitably on Android. * lisp/mouse.el (minor-mode-menu-from-indicator): New argument EVENT. Use it for positioning the menu. (mouse-minor-mode-menu): Pass EVENT to that function. * lisp/minibuffer.el (clear-minibuffer-message): Don't clear the message if `touch-screen-preview-select' may be underway. (minibuffer-mode): Enable text conversion. (minibuffer-setup-on-screen-keyboard) (minibuffer-exit-on-screen-keyboard): New functions. * lisp/menu-bar.el (menu-bar-close-window): New option. (menu-bar-edit-menu): Bind execute-extended-command to a menu item. (kill-this-buffer, kill-this-buffer-enabled-p): Respect menu-bar-close-window. * lisp/mail/rmail.el (rmail-autodetect, rmail-insert-inbox-text): Don't hard-code the name of movemail; rather, use movemail-program-name. * lisp/mail/emacsbug.el (emacs-build-description): Insert the Android version and manufacturer. * lisp/ls-lisp.el (ls-lisp-use-insert-directory-program): Default to off on Android. * lisp/loadup.el: Set load-list to empty load list after startup; dump the first time Emacs starts, and load Android related miscellanea. * lisp/isearch.el (isearch-text-conversion-style): New variable. (isearch-mode, isearch-done): Display the OSK, then temporarily disable and restore the on screen keyboard. * lisp/international/mule-cmds.el (set-coding-system-map): Update menu definition for Android. * lisp/international/fontset.el (script-representative-chars) (setup-default-fontset): Improve detection of CJK fonts. * lisp/image/wallpaper.el: Fix compiler warning. * lisp/ielm.el (inferior-emacs-lisp-mode): Don't hard-code name of hexl, replacing that with hexl-program-name. * lisp/htmlfontify.el (hfy-etags-bin): Replace hard-coded Emacs with etags-program-name. * lisp/hexl.el (hexl-program): Replace hard-coded hexl. * lisp/help-macro.el (make-help-screen): Display the on screen keyboard and disable text conversion prior to reading options. * lisp/gnus/mail-source.el (mail-source-movemail-program): Replace hard-coded movemail with movemail-program-name. * lisp/gnus/gnus-score.el (gnus-read-char): New function. (gnus-summary-increase-score): Use a dialog box to display these options on Android. * lisp/frame.el (frame-geometry, frame-edges) (mouse-absolute-pixel-position, set-mouse-absolute-pixel-position) (frame-list-z-order, frame-restack, display-mouse-p) (display-popup-menus-p, display-graphic-p, display-symbol-keys-p) (display-screens, display-pixel-height, display-pixel-width) (display-mm-height, display-mm-width, display-backing-store) (display-save-under, display-planes, display-color-cells) (display-visual-class, display-monitor-attributes-list): Implement window system specific functions on Android. * lisp/files.el (basic-save-buffer): Allow files to exist without a parent directory. * lisp/faces.el (tool-bar): Use default definition on Android. * lisp/emacs-lisp/eldoc.el (eldoc-add-command-completions): Add touch-screen-handle-touch and analyze-text-conversion. * lisp/elec-pair.el (electric-pair-analyze-conversion): New function. * lisp/doc-view.el (doc-view-menu): Improve menu. (doc-view-tool-bar-map): Add a new tool bar for Doc View. (doc-view-new-search): New command. (doc-view-mode): Enable that new tool bar. * lisp/dired-aux.el (dired-do-chxxx, dired-do-chmod) (dired-do-print, dired-do-shell-command, dired-do-compress-to) (dired-do-create-files, dired-do-rename, dired-do-isearch) (dired-do-isearch-regexp, dired-do-search) (dired-do-query-replace-regexp, dired-do-find-regexp) (dired-vc-next-action): Disable ``click to select'' after running this command. * lisp/dired.el (dired-insert-set-properties): Attach click-to-select keymap to file names if necessary. (dired-mode-map): Bind `touchscreen-hold' to click to select mode. (dired-post-do-command): New function. (dired-do-delete): Call it. (dired-mark-for-click, dired-enable-click-to-select-mode): New functions. (dired-click-to-select-mode): New minor mode. * lisp/cus-edit.el (custom-button-mouse, custom-button-pressed) (custom-display): Define faces to their default values on Android. * lisp/comint.el (comint-mode): Enable text conversion. * lisp/cedet/semantic/db-ebrowse.el (semanticdb-create-ebrowse-database): Replace fixed ebrowse with ebrowse-program-name. * lisp/calc/calc.el (calc-mode): Display the on screen keyboard. (calc): Insist on displaying the on screen keyboard. * lisp/button.el (button-map): Bind touch screen events to push-button. (push-button): Deal with touch screen events. * lisp/bindings.el (cut, paste, cut, text-conversion): New bindings. * lisp/battery.el (battery-status-function): Use `battery-android'. (battery-android): New function. * lib/gnulib.mk.in: * lib/getline.c: * lib/getdelim.c: * lib/Makefile.in: Update from Gnulib. * lib-src/emacsclient.c (decode_options): Set `alt_display' to `android'. * lib-src/asset-directory-tool.c: New file. * lib-src/Makefile.in: Adapt for cross-compilation. * java/res/xml/preferences.xml: * java/res/values/style.xml: * java/res/values/strings.xml: * java/res/values/bool.xml: * java/res/values-v29/style.xml: * java/res/values-v24/bool.xml: * java/res/values-v19/bool.xml: * java/res/values-v14/style.xml: * java/res/values-v11/style.xml: * java/org/gnu/emacs/EmacsWindowAttachmentManager.java: * java/org/gnu/emacs/EmacsWindow.java: * java/org/gnu/emacs/EmacsView.java: * java/org/gnu/emacs/EmacsThread.java: * java/org/gnu/emacs/EmacsSurfaceView.java: * java/org/gnu/emacs/EmacsService.java: * java/org/gnu/emacs/EmacsSdk8Clipboard.java: * java/org/gnu/emacs/EmacsSdk7FontDriver.java: * java/org/gnu/emacs/EmacsSdk23FontDriver.java: * java/org/gnu/emacs/EmacsSdk11Clipboard.java: * java/org/gnu/emacs/EmacsSafThread.java: * java/org/gnu/emacs/EmacsPreferencesActivity.java: * java/org/gnu/emacs/EmacsPixmap.java: * java/org/gnu/emacs/EmacsOpenActivity.java: * java/org/gnu/emacs/EmacsNoninteractive.java: * java/org/gnu/emacs/EmacsNative.java: * java/org/gnu/emacs/EmacsMultitaskActivity.java: * java/org/gnu/emacs/EmacsLauncherPreferencesActivity.java: * java/org/gnu/emacs/EmacsInputConnection.java: * java/org/gnu/emacs/EmacsHolder.java: * java/org/gnu/emacs/EmacsHandleObject.java: * java/org/gnu/emacs/EmacsGC.java: * java/org/gnu/emacs/EmacsFontDriver.java: * java/org/gnu/emacs/EmacsFillRectangle.java: * java/org/gnu/emacs/EmacsFillPolygon.java: * java/org/gnu/emacs/EmacsDrawable.java: * java/org/gnu/emacs/EmacsDrawRectangle.java: * java/org/gnu/emacs/EmacsDrawPoint.java: * java/org/gnu/emacs/EmacsDrawLine.java: * java/org/gnu/emacs/EmacsDocumentsProvider.java: * java/org/gnu/emacs/EmacsDirectoryEntry.java: * java/org/gnu/emacs/EmacsDialogButtonLayout.java: * java/org/gnu/emacs/EmacsDialog.java: * java/org/gnu/emacs/EmacsCursor.java: * java/org/gnu/emacs/EmacsContextMenu.java: * java/org/gnu/emacs/EmacsClipboard.java: * java/org/gnu/emacs/EmacsApplication.java: * java/org/gnu/emacs/EmacsActivity.java: * java/debug.sh: * java/README: * java/Makefile.in: * java/INSTALL: * java/AndroidManifest.xml.in: * exec/trace.c: * exec/test.c: * exec/mipsfpu.h: * exec/mipsfpu.c: * exec/mipsel-user.h: * exec/loader-x86_64.s: * exec/loader-x86.s: * exec/loader-mipsel.s: * exec/loader-mips64el.s: * exec/loader-armeabi.s: * exec/loader-aarch64.s: * exec/install-sh: * exec/exec1.c: * exec/exec.h: * exec/exec.c: * exec/deps.mk: * exec/configure.ac: * exec/config.sub: * exec/config.h.in: * exec/config.guess: * exec/config-mips.m4.in: * exec/README: * exec/Makefile.in: * etc/images/last-page.xpm: New files. * etc/PROBLEMS: Expound upon problems with font instructing on Android. * etc/NEWS: Announce changes. * etc/MACHINES: Describe support for Android. * etc/DEBUG: Illustrate the steps to debug Emacs on Android. * doc/lispref/processes.texi (Subprocess Creation): * doc/lispref/os.texi (System Environment): * doc/lispref/keymaps.texi (Translation Keymaps): (Extended Menu Items): (Tool Bar): * doc/lispref/frames.texi (Frames): (Frame Layout): (Font and Color Parameters): (Pop-Up Menus): (Window System Selections): * doc/lispref/elisp.texi (Top): * doc/lispref/display.texi (Defining Faces): (Window Systems): * doc/lispref/commands.texi (Touchscreen Events): (Touchscreen Events): (Misc Events): (Key Sequence Input): * doc/emacs/windows.texi (Tab Line): * doc/emacs/input.texi: * doc/emacs/frames.texi (Tool Bars): (Tab Bars): * doc/emacs/emacs.texi (Top): * doc/emacs/dired.texi (Marks vs Flags): * doc/emacs/android.texi: * doc/emacs/Makefile.in (EMACSSOURCES): Update the documentation to properly describe changes effected. * cross/verbose.mk.android: * cross/ndk-build/ndk-resolve.mk: * cross/ndk-build/ndk-prebuilt-static-library.mk: * cross/ndk-build/ndk-prebuilt-shared-library.mk: * cross/ndk-build/ndk-clear-vars.mk: * cross/ndk-build/ndk-build.mk.in: * cross/ndk-build/ndk-build-static-library.mk: * cross/ndk-build/ndk-build-shared-library.mk: * cross/ndk-build/ndk-build-executable.mk: * cross/ndk-build/README: * cross/ndk-build/Makefile.in: * cross/langinfo.h: * cross/README: * cross/Makefile.in: New files. * configure.ac: Configure Emacs for cross-compilation on Android. * build-aux/ndk-module-extract.awk: * build-aux/ndk-build-helper.mk: * build-aux/ndk-build-helper-4.mk: * build-aux/ndk-build-helper-3.mk: * build-aux/ndk-build-helper-2.mk: * build-aux/ndk-build-helper-1.mk: * build-aux/makecounter.sh: New file. * autogen.sh: Autogen in exec as well. * admin/merge-gnulib (GNULIB_MODULES): Add getline, stpncpy and strnlen. Clean lib. * README: * Makefile.in: * INSTALL: Update for Android. * .dir-locals.el (c-mode): Add a few new types.
Diffstat (limited to 'exec/exec.c')
-rw-r--r--exec/exec.c1235
1 files changed, 1235 insertions, 0 deletions
diff --git a/exec/exec.c b/exec/exec.c
new file mode 100644
index 00000000000..0d9187cabfa
--- /dev/null
+++ b/exec/exec.c
@@ -0,0 +1,1235 @@
1/* Program execution for Emacs.
2
3Copyright (C) 2023 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or (at
10your option) any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19
20#include <config.h>
21
22#include <errno.h>
23#include <unistd.h>
24#include <fcntl.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <stdlib.h>
29
30#include <sys/ptrace.h>
31#include <sys/param.h>
32#include <sys/mman.h>
33
34#include "exec.h"
35
36#if defined __mips__ && !defined MIPS_NABI
37#include "mipsfpu.h"
38#endif /* defined __mips__ && !defined MIPS_NABI */
39
40
41
42
43/* Define replacements for required string functions. */
44
45#if !defined HAVE_STPCPY || !defined HAVE_DECL_STPCPY
46
47/* Copy SRC to DEST, returning the address of the terminating '\0' in
48 DEST. */
49
50static char *
51rpl_stpcpy (char *dest, const char *src)
52{
53 register char *d;
54 register const char *s;
55
56 d = dest;
57 s = src;
58
59 do
60 *d++ = *s;
61 while (*s++ != '\0');
62
63 return d - 1;
64}
65
66#define stpcpy rpl_stpcpy
67#endif /* !defined HAVE_STPCPY || !defined HAVE_DECL_STPCPY */
68
69#if !defined HAVE_STPNCPY || !defined HAVE_DECL_STPNCPY
70
71/* Copy no more than N bytes of SRC to DST, returning a pointer past
72 the last non-NUL byte written into DST. */
73
74static char *
75rpl_stpncpy (char *dest, const char *src, size_t n)
76{
77 char c, *s;
78 size_t n4;
79
80 s = dest;
81
82 if (n >= 4)
83 {
84 n4 = n >> 2;
85
86 for (;;)
87 {
88 c = *src++;
89 *dest++ = c;
90 if (c == '\0')
91 break;
92 c = *src++;
93 *dest++ = c;
94 if (c == '\0')
95 break;
96 c = *src++;
97 *dest++ = c;
98 if (c == '\0')
99 break;
100 c = *src++;
101 *dest++ = c;
102 if (c == '\0')
103 break;
104 if (--n4 == 0)
105 goto last_chars;
106 }
107 n -= dest - s;
108 goto zero_fill;
109 }
110
111 last_chars:
112 n &= 3;
113 if (n == 0)
114 return dest;
115
116 for (;;)
117 {
118 c = *src++;
119 --n;
120 *dest++ = c;
121 if (c == '\0')
122 break;
123 if (n == 0)
124 return dest;
125 }
126
127 zero_fill:
128 while (n-- > 0)
129 dest[n] = '\0';
130
131 return dest - 1;
132}
133
134#define stpncpy rpl_stpncpy
135#endif /* !defined HAVE_STPNCPY || !defined HAVE_DECL_STPNCPY */
136
137
138
139/* Executable reading functions.
140 These functions extract information from an executable that is
141 about to be loaded.
142
143 `exec_0' takes the name of the program, determines whether or not
144 its format is correct, and if so, returns the list of actions that
145 the loader should perform.
146
147 The actions include:
148
149 - Making the stack executable, if PT_GNU_STACK.
150 - Mapping PT_LOAD sections into the executable with the correct
151 memory protection.
152 - On MIPS, setting the floating point register size.
153 - Transferring control to the interpreter or executable. */
154
155
156/* Check whether or not FD starts with a #!, and return the executable
157 to load if it does. Value is NAME if no interpreter character was
158 found, or the interpreter otherwise. Value is NULL upon an IO
159 error.
160
161 If an additional command line argument is specified, place it in
162 *EXTRA. */
163
164static const char *
165check_interpreter (const char *name, int fd, const char **extra)
166{
167 static char buffer[PATH_MAX], *start;
168 char first[2], *end, *ws;
169 ssize_t rc;
170
171 /* Read the first character. */
172 rc = read (fd, &first, 2);
173
174 if (rc != 2)
175 goto fail;
176
177 if (first[0] != '#' || first[1] != '!')
178 goto nomatch;
179
180 rc = read (fd, buffer, PATH_MAX);
181
182 if (rc < 0)
183 goto fail;
184
185 /* Strip leading whitespace. */
186 start = buffer;
187 while (*start && ((unsigned char) *start) < 128 && isspace (*start))
188 ++start;
189
190 /* Look for a newline character. */
191 end = memchr (start, '\n', rc);
192
193 if (!end)
194 goto fail;
195
196 /* The string containing the interpreter is now in start. NULL
197 terminate it. */
198 *end = '\0';
199
200 /* Now look for any whitespace characters. */
201 ws = strchr (start, ' ');
202
203 /* If there's no whitespace, return the entire start. */
204
205 if (!ws)
206 {
207 if (lseek (fd, 0, SEEK_SET))
208 goto fail;
209
210 return start;
211 }
212
213 /* Otherwise, split the string at the whitespace and return the
214 additional argument. */
215 *ws = '\0';
216
217 if (lseek (fd, 0, SEEK_SET))
218 goto fail;
219
220 *extra = ws + 1;
221 return start;
222
223 nomatch:
224 /* There's no interpreter. */
225 if (lseek (fd, 0, SEEK_SET))
226 goto fail;
227
228 return name;
229
230 fail:
231 errno = ENOEXEC;
232 return NULL;
233}
234
235/* Static area used to store data placed on the loader's stack. */
236static char loader_area[65536];
237
238/* Number of bytes used in that area. */
239static int loader_area_used;
240
241
242
243/* Structure definitions for commands placed in the loader area.
244 Arrange these so that each member is naturally aligned. */
245
246struct exec_open_command
247{
248 /* Word identifying the type of this command. */
249 USER_WORD command;
250
251 /* NULL-terminated file name follows, padded to the size of a user
252 word. */
253};
254
255struct exec_map_command
256{
257 /* Word identifying the type of this command. */
258 USER_WORD command;
259
260 /* Where the file will be mapped. */
261 USER_WORD vm_address;
262
263 /* Offset into the file to map from. */
264 USER_WORD file_offset;
265
266 /* Memory protection for mprotect. */
267 USER_WORD protection;
268
269 /* Number of bytes to be mapped. */
270 USER_WORD length;
271
272 /* Flags for mmap. */
273 USER_WORD flags;
274
275 /* Number of bytes to clear at the end of this mapping. */
276 USER_WORD clear;
277};
278
279struct exec_jump_command
280{
281 /* Word identifying the type of this command. */
282 USER_WORD command;
283
284 /* Address to jump to. */
285 USER_WORD entry;
286
287 /* The value of AT_ENTRY inside the aux vector. */
288 USER_WORD at_entry;
289
290 /* The value of AT_PHENT inside the aux vector. */
291 USER_WORD at_phent;
292
293 /* The value of AT_PHNUM inside the aux vector. */
294 USER_WORD at_phnum;
295
296 /* The value of AT_PHDR inside the aux vector. */
297 USER_WORD at_phdr;
298
299 /* The value of AT_BASE inside the aux vector. */
300 USER_WORD at_base;
301
302#if defined __mips__ && !defined MIPS_NABI
303 /* The FPU mode to apply. */
304 USER_WORD fpu_mode;
305#endif /* defined __mips__ && !defined MIPS_NABI */
306};
307
308
309
310/* Write a command to open the file NAME to the loader area.
311 If ALTERNATE is true, then use the command code 16 instead
312 of 0. Value is 1 upon failure, else 0. */
313
314static int
315write_open_command (const char *name, bool alternate)
316{
317 struct exec_open_command command;
318 size_t size;
319
320 /* First, write the command to open NAME. This is followed by NAME
321 itself, padded to sizeof (USER_WORD) bytes. */
322
323 command.command = alternate ? 16 : 0;
324 if (sizeof loader_area - loader_area_used < sizeof command)
325 return 1;
326 memcpy (loader_area + loader_area_used, &command, sizeof command);
327 loader_area_used += sizeof command;
328
329 /* Calculate the length of NAME. */
330 size = strlen (name) + 1;
331
332 /* Round it up. */
333 size = ((size + (sizeof (USER_WORD) - 1))
334 & ~(sizeof (USER_WORD) - 1));
335
336 if (sizeof loader_area - loader_area_used < size)
337 return 1;
338
339 /* Now copy name to the loader area, filling the padding with NULL
340 bytes. */
341 strncpy (loader_area + loader_area_used, name, size);
342
343 /* Increase loader_area_used. */
344 loader_area_used += size;
345 return 0;
346}
347
348/* Write the commands necessary to map the executable file into memory
349 for the given PT_LOAD program HEADER. Value is 1 upon failure,
350 else 0. If USE_ALTERNATE, use the command code 17 instead of
351 1.
352
353 Apply the given OFFSET to virtual addresses that will be mapped. */
354
355static int
356write_load_command (program_header *header, bool use_alternate,
357 USER_WORD offset)
358{
359 struct exec_map_command command;
360 struct exec_map_command command1;
361 USER_WORD start, end;
362 bool need_command1;
363 static long pagesize;
364
365 /* First, write the commands necessary to map the specified segment
366 itself.
367
368 This is the area between header->p_vaddr and header->p_filesz,
369 rounded up to the page size. */
370
371#ifndef PAGE_MASK
372 /* This system doesn't define a fixed page size. */
373
374#ifdef HAVE_GETPAGESIZE
375 if (!pagesize)
376 pagesize = getpagesize ();
377#else /* HAVE_GETPAGESIZE */
378 if (!pagesize)
379 pagesize = sysconf (_SC_PAGESIZE);
380
381#define PAGE_MASK (~(pagesize - 1))
382#define PAGE_SIZE (pagesize)
383#endif /* HAVE_GETPAGESIZE */
384#endif /* PAGE_MASK */
385
386 start = header->p_vaddr & PAGE_MASK;
387 end = ((header->p_vaddr + header->p_filesz
388 + PAGE_SIZE)
389 & PAGE_MASK);
390
391 command.command = use_alternate ? 17 : 1;
392 command.vm_address = start;
393 command.file_offset = header->p_offset & PAGE_MASK;
394 command.protection = 0;
395 command.length = end - start;
396 command.clear = 0;
397 command.flags = MAP_PRIVATE | MAP_FIXED;
398
399 /* Apply the memory protection specified in the header. */
400
401 if (header->p_flags & 4) /* PF_R */
402 command.protection |= PROT_READ;
403
404 if (header->p_flags & 2) /* PF_W */
405 command.protection |= PROT_WRITE;
406
407 if (header->p_flags & 1) /* PF_X */
408 command.protection |= PROT_EXEC;
409
410 /* Next, write any command necessary to map pages in the area
411 between p_filesz and p_memsz. */
412 need_command1 = false;
413
414 if (header->p_memsz > header->p_filesz)
415 {
416 /* If there are bytes after end which need to be initialized, do
417 that now. */
418 command.clear = end - header->p_vaddr - header->p_filesz;
419 start = end;
420 end = header->p_vaddr + header->p_memsz + PAGE_SIZE;
421 end &= PAGE_MASK;
422
423 if (end > start)
424 {
425 command1.command = 4;
426 command1.vm_address = start;
427 command1.file_offset = 0;
428 command1.length = end - start;
429 command1.clear = 0;
430 command1.protection = command.protection;
431 command1.flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED;
432 need_command1 = true;
433 }
434 }
435
436 /* Apply the offset to both commands if necessary. */
437
438 if (offset)
439 {
440 if (need_command1)
441 command1.vm_address += offset;
442
443 command.vm_address += offset;
444 }
445
446 /* Write both commands. */
447
448 if (sizeof loader_area - loader_area_used < sizeof command)
449 return 1;
450
451 memcpy (loader_area + loader_area_used, &command,
452 sizeof command);
453 loader_area_used += sizeof command;
454
455 if (!need_command1)
456 return 0;
457
458 if (sizeof loader_area - loader_area_used < sizeof command1)
459 return 1;
460
461 memcpy (loader_area + loader_area_used, &command1,
462 sizeof command1);
463 loader_area_used += sizeof command1;
464
465 return 0;
466}
467
468#if defined __mips__ && !defined MIPS_NABI
469
470/* Static storage used for MIPS ABI flags. */
471static struct mips_elf_abi_flags exec_abi, interpreter_abi;
472
473/* Static storage for interpreter headers. */
474static elf_header exec_interpreter_header;
475
476/* Pointer to the ELF header of this executable's interpreter. */
477static elf_header *interpreter_header;
478
479/* Pointer to any PT_MIPS_ABIFLAGS program header found in the
480 executable itself. */
481static struct mips_elf_abi_flags *exec_abiflags;
482
483/* Pointer to any PT_MIPS_ABIFLAGS program header found in the
484 executable's ELF interpreter. */
485static struct mips_elf_abi_flags *interpreter_abiflags;
486
487#endif /* defined __mips__ && !defined MIPS_NABI */
488
489/* Process the specified program HEADER; HEADER is from the ELF
490 interpreter of another executable. FD is the executable file from
491 which it is being read, NAME is its file name, and ELF_HEADER is
492 its header.
493
494 If ELF_HEADER->e_type is ET_DYN, add the base address for position
495 independent interpreter code to virtual addresses.
496
497 Value is 1 upon failure, else 0. */
498
499static int
500process_interpreter_1 (const char *name, int fd,
501 program_header *header,
502 elf_header *elf_header)
503{
504 int rc;
505#if defined __mips__ && !defined MIPS_NABI
506 ssize_t rc1;
507#endif /* defined __mips__ && !defined MIPS_NABI */
508
509 switch (header->p_type)
510 {
511 default: /* PT_NULL, PT_NOTE, PT_DYNAMIC, PT_INTERP, et cetera */
512 rc = 0;
513 break;
514
515 case 1: /* PT_LOAD */
516 /* This describes a segment in the file that must be loaded.
517 Write the appropriate load command. */
518
519 if (elf_header->e_type == 3) /* ET_DYN */
520 rc = write_load_command (header, true,
521 INTERPRETER_BASE);
522 else
523 rc = write_load_command (header, true, 0);
524
525 break;
526
527#if defined __mips__ && !defined MIPS_NABI
528 case 0x70000003: /* PT_MIPS_ABIFLAGS */
529 /* Record this header for later use. */
530 rc1 = pread (fd, &interpreter_abi, sizeof interpreter_abi,
531 header->p_offset);
532
533 if (rc1 != sizeof interpreter_abi)
534 return 1;
535
536 interpreter_abiflags = &interpreter_abi;
537 rc = 0;
538#endif /* defined __mips__ && !defined MIPS_NABI */
539 }
540
541 return rc;
542}
543
544/* Read the ELF interpreter specified in the given program header from
545 FD, and append the commands necessary to load it to the load area.
546 Then, return the interpreter entry point in *ENTRY.
547
548 Value is 1 upon failure, else 0. */
549
550static int
551process_interpreter (int fd, program_header *prog_header,
552 USER_WORD *entry)
553{
554 char buffer[PATH_MAX + 1];
555 int rc, size, i;
556 elf_header header;
557 program_header program;
558
559 /* Read the interpreter name. */
560 size = MIN (prog_header->p_filesz, PATH_MAX);
561 rc = pread (fd, buffer, size, prog_header->p_offset);
562 if (rc < size)
563 return 1;
564
565 /* Make sure the name is NULL terminated. */
566 buffer[size] = '\0';
567
568 /* Check if the file is executable. This is unfortunately not
569 atomic. */
570
571 if (access (buffer, X_OK))
572 return 1;
573
574 /* Read the interpreter's header much like exec_0.
575
576 However, use special command codes in `process_program_header' if
577 it is position independent. That way, the loader knows it should
578 use the open interpreter instead. */
579
580 fd = open (buffer, O_RDONLY);
581
582 if (fd < 0)
583 return 1;
584
585 rc = read (fd, &header, sizeof header);
586
587 if (rc < sizeof header)
588 goto fail;
589
590#if defined __mips__ && !defined MIPS_NABI
591 /* Record this interpreter's header for later use determining the
592 floating point ABI. */
593 exec_interpreter_header = header;
594 interpreter_header = &exec_interpreter_header;
595#endif /* defined __mips__ && !defined MIPS_NABI */
596
597 /* Verify that this is indeed an ELF file. */
598
599 if (header.e_ident[0] != 0x7f
600 || header.e_ident[1] != 'E'
601 || header.e_ident[2] != 'L'
602 || header.e_ident[3] != 'F')
603 goto fail;
604
605 /* Now check that the class is correct. */
606#ifdef EXEC_64
607 if (header.e_ident[4] != 2)
608 goto fail;
609#else /* !EXEC_64 */
610 if (header.e_ident[4] != 1)
611 goto fail;
612#endif /* EXEC_64 */
613
614 /* And the endianness. */
615#ifndef WORDS_BIGENDIAN
616 if (header.e_ident[5] != 1)
617 goto fail;
618#else /* WORDS_BIGENDIAN */
619 if (header.e_ident[5] != 2)
620 goto fail;
621#endif /* EXEC_64 */
622
623 /* Check that this is an executable. */
624 if (header.e_type != 2 && header.e_type != 3)
625 goto fail;
626
627 /* Now check that the ELF program header makes sense. */
628 if (header.e_phnum > 0xffff
629 || (header.e_phentsize
630 != sizeof (program_header)))
631 goto fail;
632
633 if (write_open_command (buffer, true))
634 goto fail;
635
636 for (i = 0; i < header.e_phnum; ++i)
637 {
638 rc = read (fd, &program, sizeof program);
639 if (rc < sizeof program)
640 goto fail;
641
642 if (process_interpreter_1 (buffer, fd, &program,
643 &header))
644 goto fail;
645 }
646
647 if (header.e_type == 3) /* ET_DYN */
648 *entry = header.e_entry + INTERPRETER_BASE;
649 else
650 *entry = header.e_entry;
651
652 close (fd);
653 return 0;
654
655 fail:
656 close (fd);
657 return 1;
658}
659
660/* Process the specified program HEADER. FD is the executable file
661 from which it is being read, NAME is its file name, and ELF_HEADER
662 is its header.
663
664 If ELF_HEADER->e_type is ET_DYN, add the base address for position
665 independent code to virtual addresses.
666
667 If OFFSET is non-NULL, and *OFFSET is -1, write the virtual address
668 of HEADER if it describes a PT_LOAD segment.
669
670 If an interpreter is found, set *ENTRY to its entry point.
671
672 Value is 1 upon failure, else 0. */
673
674static int
675process_program_header (const char *name, int fd,
676 program_header *header,
677 elf_header *elf_header,
678 USER_WORD *entry,
679 USER_WORD *offset)
680{
681 int rc;
682#if defined __mips__ && !defined MIPS_NABI
683 ssize_t rc1;
684#endif /* defined __mips__ && !defined MIPS_NABI */
685
686 switch (header->p_type)
687 {
688 default: /* PT_NULL, PT_NOTE, PT_DYNAMIC, et cetera */
689 rc = 0;
690 break;
691
692 case 1: /* PT_LOAD */
693 /* This describes a segment in the file that must be loaded.
694 Write the appropriate load command. */
695
696 if (elf_header->e_type == 3) /* ET_DYN */
697 {
698 rc = write_load_command (header, false,
699 EXECUTABLE_BASE);
700
701 if (!rc && offset && *offset == (USER_WORD) -1)
702 *offset = EXECUTABLE_BASE + header->p_vaddr;
703 }
704 else
705 {
706 rc = write_load_command (header, false, 0);
707
708 if (!rc && offset && *offset == (USER_WORD) -1)
709 *offset = header->p_vaddr;
710 }
711
712 break;
713
714 case 3: /* PT_INTERP */
715 /* This describes another executable that must be loaded. Open
716 the interpreter and process each of its headers as well. */
717 rc = process_interpreter (fd, header, entry);
718 break;
719
720 case 1685382481: /* PT_GNU_STACK */
721 /* TODO */
722 rc = 0;
723 break;
724
725#if defined __mips__ && !defined MIPS_NABI
726 case 0x70000003: /* PT_MIPS_ABIFLAGS */
727 /* Record this header for later use. */
728 rc1 = pread (fd, &exec_abi, sizeof exec_abi,
729 header->p_offset);
730
731 if (rc1 != sizeof exec_abi)
732 return 1;
733
734 exec_abiflags = &exec_abi;
735 rc = 0;
736#endif /* defined __mips__ && !defined MIPS_NABI */
737 }
738
739 return rc;
740}
741
742/* Prepend one or two extra arguments ARG1 and ARG2 to a pending
743 execve system call. Replace the argument immediately after
744 with ARG3.
745
746 TRACEE is the tracee performing the system call, and REGS are its
747 current user registers. Value is 1 upon failure, else 0. */
748
749static int
750insert_args (struct exec_tracee *tracee, USER_REGS_STRUCT *regs,
751 const char *arg1, const char *arg2, const char *arg3)
752{
753 USER_WORD argv, argc, word, new;
754 USER_WORD new1, new2, new3, i;
755 size_t text_size, effective_size;
756 USER_REGS_STRUCT original;
757
758 /* First, get a pointer to the current argument vector. */
759 argv = regs->SYSCALL_ARG1_REG;
760
761 /* Now figure out how many arguments there are. */
762 argc = 0;
763 while (true)
764 {
765 /* Clear errno. PTRACE_PEEKDATA returns the word read the same
766 way failure indications are returned, so the only way to
767 catch IO errors is by clearing errno before the call to
768 ptrace and checking it afterwards. */
769
770 errno = 0;
771 word = ptrace (PTRACE_PEEKDATA, tracee->pid,
772 (void *) argv, NULL);
773 argv += sizeof (USER_WORD);
774
775 if (errno)
776 return 1;
777
778 if (!word)
779 break;
780
781 ++argc;
782 };
783
784 /* Allocate enough to hold that many arguments, alongside the argc
785 text. */
786
787 text_size = (strlen (arg1) + 1
788 + (arg2 ? strlen (arg2) + 1 : 0)
789 + strlen (arg3) + 1);
790
791 /* Round it up to the user word size. */
792 text_size += sizeof (USER_WORD) - 1;
793 text_size &= ~(sizeof (USER_WORD) - 1);
794
795 /* Now allocate the new argv. Make sure argc is at least 1; it
796 needs to hold ARG3. */
797
798 effective_size = sizeof word * (MAX (1, argc) + 2) + text_size;
799
800 if (arg2)
801 effective_size += sizeof word;
802
803 /* Copy regs to original so that user_alloca knows it should append
804 the ABI red zone. */
805
806 memcpy (&original, regs, sizeof *regs);
807 new = user_alloca (tracee, &original, regs,
808 effective_size);
809
810 if (!new)
811 goto fail;
812
813 /* Figure out where argv starts. */
814
815 new3 = new + text_size;
816
817 /* Now write the first two strings. */
818
819 new1 = new + strlen (arg1) + 1;
820 new2 = new1 + (arg2 ? strlen (arg2) + 1 : 0);
821
822 if (user_copy (tracee, (const unsigned char *) arg1,
823 new, new1 - new))
824 goto fail;
825
826 if (arg2 && user_copy (tracee, (const unsigned char *) arg2,
827 new1, new2 - new1))
828 goto fail;
829
830 /* Write the replacement arg3, the file name of the executable. */
831
832 if (user_copy (tracee, (const unsigned char *) arg3,
833 new2, new3 - new2))
834 goto fail;
835
836 /* Start copying argv back to new2. First, write the one or two new
837 arguments. */
838
839 if (ptrace (PTRACE_POKETEXT, tracee->pid,
840 (void *) new3, (void *) new))
841 goto fail;
842
843 new3 += sizeof new3;
844
845 if (arg2 && ptrace (PTRACE_POKETEXT, tracee->pid,
846 (void *) new3, (void *) new1))
847 goto fail;
848 else if (arg2)
849 new3 += sizeof new3;
850
851 /* Next, write the third argument. */
852
853 if (ptrace (PTRACE_POKETEXT, tracee->pid, (void *) new3,
854 (void *) new2))
855 goto fail;
856
857 new3 += sizeof new3;
858
859 /* Copy the remaining arguments back. */
860
861 argv = regs->SYSCALL_ARG1_REG;
862
863 if (argc)
864 {
865 /* Make sure the trailing NULL is included. */
866 argc += 1;
867
868 /* Now copy each argument in argv, starting from argv[1]. */
869
870 for (i = 1; i < argc; ++i)
871 {
872 /* Read one argument. */
873 word = ptrace (PTRACE_PEEKDATA, tracee->pid,
874 (void *) (argv + i * sizeof argv), NULL);
875
876 /* Write one argument, then increment new3. */
877
878 if (ptrace (PTRACE_POKETEXT, tracee->pid,
879 (void *) new3, (void *) word))
880 goto fail;
881
882 new3 += sizeof new3;
883 }
884 }
885 else
886 {
887 /* Just write the trailing NULL. */
888
889 if (ptrace (PTRACE_POKETEXT, tracee->pid,
890 (void *) new3, (void *) 0))
891 goto fail;
892
893 new3 += sizeof new3;
894 }
895
896 /* Assert that new3 is not out of bounds. */
897 assert (new3 == new + effective_size);
898
899 /* And that it is properly aligned. */
900 assert (!(new3 & (sizeof new3 - 2)));
901
902 /* Now modify the system call argument to point to new +
903 text_size. */
904
905 regs->SYSCALL_ARG1_REG = new + text_size;
906
907#ifdef __aarch64__
908 if (aarch64_set_regs (tracee->pid, regs, false))
909 goto fail;
910#else /* !__aarch64__ */
911 if (ptrace (PTRACE_SETREGS, tracee->pid, NULL, regs))
912 goto fail;
913#endif /* __aarch64__ */
914
915 /* Success. */
916
917 return 0;
918
919 fail:
920 /* Restore the original stack pointer. */
921#ifdef __aarch64__
922 aarch64_set_regs (tracee->pid, &original, false);
923#else /* !__aarch64__ */
924 ptrace (PTRACE_SETREGS, tracee->pid, NULL, &original);
925#endif /* __aarch64__ */
926 errno = ENOMEM;
927 return 1;
928}
929
930
931
932/* Format PID, an unsigned process identifier, in base 10. Place the
933 result in *IN, and return a pointer to the byte after the
934 result. REM should be NULL. */
935
936static char *
937format_pid (char *in, unsigned int pid)
938{
939 unsigned int digits[32], *fill;
940
941 fill = digits;
942
943 for (; pid != 0; pid = pid / 10)
944 *fill++ = pid % 10;
945
946 /* Insert 0 if the number would otherwise be empty. */
947
948 if (fill == digits)
949 *fill++ = 0;
950
951 while (fill != digits)
952 {
953 --fill;
954 *in++ = '0' + *fill;
955 }
956
957 *in = '\0';
958 return in;
959}
960
961/* Return a sequence of actions required to load the executable under
962 the file NAME for the given TRACEE. First, see if the file starts
963 with #!; in that case, find the program to open and use that
964 instead.
965
966 If REENTRANT is not defined, NAME is actually a buffer of size
967 PATH_MAX + 80. In that case, copy over the file name actually
968 opened.
969
970 Next, read the executable header, and add the necessary memory
971 mappings for each file. Finally, return the action data and its
972 size in *SIZE.
973
974 Finally, use REGS to add the required interpreter arguments to the
975 caller's argv.
976
977 Value is NULL upon failure, with errno set accordingly. */
978
979char *
980exec_0 (char *name, struct exec_tracee *tracee,
981 size_t *size, USER_REGS_STRUCT *regs)
982{
983 int fd, rc, i;
984 elf_header header;
985 const char *interpreter_name, *extra;
986 program_header program;
987 USER_WORD entry, program_entry, offset;
988 USER_WORD header_offset;
989 struct exec_jump_command jump;
990#if defined __mips__ && !defined MIPS_NABI
991 int fpu_mode;
992#endif /* defined __mips__ && !defined MIPS_NABI */
993 char buffer[80], buffer1[PATH_MAX + 80], *rewrite;
994 ssize_t link_size;
995 size_t remaining;
996
997 /* If the process is trying to run /proc/self/exe, make it run
998 itself instead. */
999
1000 if (!strcmp (name, "/proc/self/exe") && tracee->exec_file)
1001 {
1002 strncpy (name, tracee->exec_file, PATH_MAX - 1);
1003 name[PATH_MAX] = '\0';
1004 }
1005 else
1006 {
1007 /* If name is not absolute, then make it relative to TRACEE's
1008 cwd. Use stpcpy, as sprintf is not reentrant. */
1009
1010 if (name[0] && name[0] != '/')
1011 {
1012 /* Clear `buffer'. */
1013 memset (buffer, 0, sizeof buffer);
1014 memset (buffer1, 0, sizeof buffer);
1015
1016 /* Copy over /proc, the PID, and /cwd/. */
1017 rewrite = stpcpy (buffer, "/proc/");
1018 rewrite = format_pid (rewrite, tracee->pid);
1019 strcpy (rewrite, "/cwd");
1020
1021 /* Resolve this symbolic link. */
1022
1023 link_size = readlink (buffer, buffer1,
1024 PATH_MAX + 1);
1025
1026 if (link_size < 0)
1027 return NULL;
1028
1029 /* Check that the name is a reasonable size. */
1030
1031 if (link_size > PATH_MAX)
1032 {
1033 /* The name is too long. */
1034 errno = ENAMETOOLONG;
1035 return NULL;
1036 }
1037
1038 /* Add a directory separator if necessary. */
1039
1040 if (!link_size || buffer1[link_size - 1] != '/')
1041 buffer1[link_size] = '/', link_size++;
1042
1043 rewrite = buffer1 + link_size;
1044 remaining = buffer1 + sizeof buffer1 - rewrite - 1;
1045 rewrite = stpncpy (rewrite, name, remaining);
1046
1047 /* Replace name with buffer1. */
1048#ifndef REENTRANT
1049 strcpy (name, buffer1);
1050#endif /* REENTRANT */
1051 }
1052 }
1053
1054 /* Check that the file is accessible and executable. */
1055
1056 if (access (name, X_OK))
1057 return NULL;
1058
1059 fd = open (name, O_RDONLY);
1060 if (fd < 0)
1061 return NULL;
1062
1063 /* Now read the header. */
1064
1065 extra = NULL;
1066 interpreter_name = check_interpreter (name, fd, &extra);
1067 if (!interpreter_name)
1068 goto fail;
1069
1070 /* Open the interpreter instead, if necessary. */
1071 if (interpreter_name != name)
1072 {
1073 close (fd);
1074 fd = open (interpreter_name, O_RDONLY);
1075 if (fd < 0)
1076 return NULL;
1077
1078 /* Now, rewrite the argument list to include `interpreter_name'
1079 and perhaps `extra'. */
1080
1081 if (insert_args (tracee, regs, interpreter_name,
1082 extra, name))
1083 goto fail1;
1084 }
1085
1086 rc = read (fd, &header, sizeof header);
1087
1088 if (rc < sizeof header)
1089 goto fail1;
1090
1091 /* Verify that this is indeed an ELF file. */
1092
1093 if (header.e_ident[0] != 0x7f
1094 || header.e_ident[1] != 'E'
1095 || header.e_ident[2] != 'L'
1096 || header.e_ident[3] != 'F')
1097 goto fail1;
1098
1099 /* Now check that the class is correct. */
1100#ifdef EXEC_64
1101 if (header.e_ident[4] != 2)
1102 goto fail1;
1103#else /* !EXEC_64 */
1104 if (header.e_ident[4] != 1)
1105 goto fail1;
1106#endif /* EXEC_64 */
1107
1108 /* And the endianness. */
1109#ifndef WORDS_BIGENDIAN
1110 if (header.e_ident[5] != 1)
1111 goto fail1;
1112#else /* WORDS_BIGENDIAN */
1113 if (header.e_ident[5] != 2)
1114 goto fail1;
1115#endif /* EXEC_64 */
1116
1117 /* Check that this is an executable. */
1118 if (header.e_type != 2 && header.e_type != 3)
1119 goto fail1;
1120
1121 /* Now check that the ELF program header makes sense. */
1122 if (header.e_phnum > 0xffff
1123 || (header.e_phentsize
1124 != sizeof (program_header)))
1125 goto fail1;
1126
1127 /* Seek to the first program header and read each one. */
1128 rc = lseek (fd, header.e_phoff, SEEK_SET);
1129 if (rc < 0)
1130 goto fail1;
1131 loader_area_used = 0;
1132
1133 /* Write the command used to open the executable. */
1134 if (write_open_command (interpreter_name, false))
1135 goto fail1;
1136
1137 /* Apply base addresses for PIC code. */
1138
1139 if (header.e_type == 3) /* ET_DYN */
1140 offset = EXECUTABLE_BASE;
1141 else
1142 offset = 0;
1143
1144 /* entry and program_entry are initially the same, but entry may be
1145 set to that of the interpreter if one is present. */
1146
1147 entry = header.e_entry + offset;
1148 program_entry = header.e_entry;
1149
1150#if defined __mips__ && !defined MIPS_NABI
1151 /* Clear MIPS ABI flags. */
1152 exec_abiflags = NULL;
1153 interpreter_abiflags = NULL;
1154 interpreter_header = NULL;
1155#endif /* defined __mips__ && !defined MIPS_NABI */
1156
1157 /* Set header_offset to -1; `process_program_header' then updates it
1158 to that of the first mapping. */
1159 header_offset = -1;
1160
1161 for (i = 0; i < header.e_phnum; ++i)
1162 {
1163 rc = read (fd, &program, sizeof program);
1164 if (rc < sizeof program)
1165 goto fail1;
1166
1167 if (process_program_header (interpreter_name, fd,
1168 &program, &header,
1169 &entry, &header_offset))
1170 goto fail1;
1171 }
1172
1173 /* Write the entry point and program entry. */
1174
1175 jump.command = 3;
1176 jump.entry = entry;
1177
1178 /* Now calculate values for the aux vector. */
1179
1180 jump.at_entry = program_entry + offset;
1181 jump.at_phent = header.e_phentsize;
1182 jump.at_phnum = header.e_phnum;
1183 jump.at_base = (entry == header.e_entry + offset
1184 ? EXECUTABLE_BASE
1185 : INTERPRETER_BASE);
1186
1187#if defined __mips__ && !defined MIPS_NABI
1188 /* Finally, calculate the FPU mode wanted by the executable. */
1189
1190 if (determine_fpu_mode (&header, interpreter_header,
1191 &fpu_mode, exec_abiflags,
1192 interpreter_abiflags))
1193 /* N.B. that `determine_fpu_mode' sets errno. */
1194 goto fail;
1195
1196 /* If the processor is too new to support FR0 operation, place the
1197 executable in floating point emulation mode. */
1198
1199 if (fpu_mode == FP_FR0 && !cpu_supports_fr0_p ())
1200 fpu_mode = FP_FRE;
1201
1202 jump.fpu_mode = fpu_mode;
1203#endif /* defined __mips__ && !defined MIPS_NABI */
1204
1205 /* The offset used for at_phdr should be that of the first
1206 mapping. */
1207
1208 if (header_offset == (USER_WORD) -1)
1209 header_offset = 0;
1210
1211 jump.at_phdr = header.e_phoff + header_offset;
1212
1213 if (sizeof loader_area - loader_area_used < sizeof jump)
1214 goto fail1;
1215
1216 memcpy (loader_area + loader_area_used, &jump,
1217 sizeof jump);
1218 loader_area_used += sizeof jump;
1219
1220 /* Close the file descriptor and return the number of bytes
1221 used. */
1222
1223 close (fd);
1224 *size = loader_area_used;
1225
1226 /* Make sure the loader area is properly aligned. */
1227 assert (!(loader_area_used & (sizeof (USER_WORD) - 1)));
1228 return loader_area;
1229
1230 fail1:
1231 errno = ENOEXEC;
1232 fail:
1233 close (fd);
1234 return NULL;
1235}