aboutsummaryrefslogtreecommitdiffstats
path: root/exec
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
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')
-rw-r--r--exec/Makefile.in140
-rw-r--r--exec/README3
-rw-r--r--exec/config-mips.m4.in42
-rwxr-xr-xexec/config.guess1768
-rw-r--r--exec/config.h.in358
-rwxr-xr-xexec/config.sub1890
-rw-r--r--exec/configure.ac537
-rw-r--r--exec/deps.mk21
-rw-r--r--exec/exec.c1235
-rw-r--r--exec/exec.h201
-rw-r--r--exec/exec1.c94
-rwxr-xr-xexec/install-sh541
-rw-r--r--exec/loader-aarch64.s187
-rw-r--r--exec/loader-armeabi.s204
-rw-r--r--exec/loader-mips64el.s234
-rw-r--r--exec/loader-mipsel.s236
-rw-r--r--exec/loader-x86.s203
-rw-r--r--exec/loader-x86_64.s195
-rw-r--r--exec/mipsel-user.h43
-rw-r--r--exec/mipsfpu.c289
-rw-r--r--exec/mipsfpu.h82
-rw-r--r--exec/test.c105
-rw-r--r--exec/trace.c1432
23 files changed, 10040 insertions, 0 deletions
diff --git a/exec/Makefile.in b/exec/Makefile.in
new file mode 100644
index 00000000000..00e59771337
--- /dev/null
+++ b/exec/Makefile.in
@@ -0,0 +1,140 @@
1### @configure_input@
2
3# Copyright (C) 2023 Free Software Foundation, Inc.
4
5# This file is part of GNU Emacs.
6
7# GNU Emacs is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11
12# GNU Emacs is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16
17# You should have received a copy of the GNU General Public License
18# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20# Configure build directory information.
21
22 srcdir = @srcdir@
23 VPATH = @srcdir@
24 builddir = @builddir@
25
26# Set up compilation tools.
27
28 CC = @CC@
29 AS = @AS@
30 LD = @LD@
31 M4 = @M4@
32 CPP = @CPP@
33 ASFLAGS = @ASFLAGS@
34 ARFLAGS = @ARFLAGS@
35 CFLAGS = @CFLAGS@
36 CPPFLAGS = @CPPFLAGS@
37 LDFLAGS = @LDFLAGS@
38LOADERFLAGS = @LOADERFLAGS@
39FIND_DELETE = @FIND_DELETE@
40
41# Set up object files.
42
43 LOADER = @exec_loader@
44 OBJS = @OBJS@
45 LOADOBJS = $(patsubst %.s,%.o,$(LOADER))
46
47# Set up automatic dependency tracking.
48
49AUTO_DEPEND = @AUTO_DEPEND@
50DEPDIR = deps
51ifeq ($(AUTO_DEPEND),yes)
52DEPFLAGS = -MMD -MF $(DEPDIR)/$*.d -MP
53-include $(OBJS:%.o=$(DEPDIR)/%.d)
54-include $(DEPDIR)/test.d
55-include $(DEPDIR)/exec1.d
56else
57DEPFLAGS =
58include $(srcdir)/deps.mk
59endif
60
61# Set up the appropriate targets.
62
63all: libexec.a loader
64
65# Set up automatic Makefile regeneration.
66
67$(srcdir)/configure: $(srcdir)/configure.ac
68 cd $(srcdir) && autoreconf
69
70config.status: $(srcdir)/configure
71 if [ -x config.status ]; then \
72 ./config.status --recheck; \
73 else \
74 $(srcdir)/configure; \
75 fi
76
77Makefile: config.status Makefile.in
78 MAKE="$(MAKE)" ./config.status
79
80# Set up rules to build targets.
81
82.SUFFIXES: .c .s
83.c.o:
84 $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEPFLAGS) -I. -I$(srcdir) $< -o $@
85.s.o:
86 $(M4) $< > $(notdir $<).s
87 $(AS) $(ASFLAGS) $(notdir $<).s -o $@
88
89# Set up dependencies for config-mips.m4.
90
91config-mips.m4: config-mips.m4.in
92 cd $(srcdir) && ./config.status $@
93$(LOADOBJS): config-mips.m4
94
95# Set up rules to build libexec.a.
96
97libexec.a: $(OBJS)
98 $(AR) cru $(ARFLAGS) $@ $^
99
100# And loader.
101
102loader: $(LOADOBJS)
103 $(LD) -o $@ $(LOADERFLAGS) $(LOADOBJS)
104
105# And test.
106
107test: test.o libexec.a
108 $(CC) $(LDFLAGS) $< libexec.a -o $@
109
110# And exec1.
111
112exec1: exec1.o libexec.a
113 $(CC) $(LDFLAGS) $< libexec.a -o $@
114
115# Set up targets for cleaning.
116
117.PHONY: clean distclean maintainer-clean extraclean bootstrap-clean
118clean:
119 rm -f *.o *.a loader test exec1 *.s.s
120ifeq ($(AUTO_DEPEND),yes)
121 rm -rf deps/*.d
122endif
123
124distclean: clean
125 rm -f Makefile config.status config.h config-mips.m4
126
127maintainer-clean: distclean
128
129### This doesn't actually appear in the coding standards, but Karl
130### says GCC supports it, and that's where the configuration part of
131### the coding standards seem to come from. It's like distclean, but
132### it deletes backup and autosave files too.
133
134extraclean: maintainer-clean
135 -rm -f config-tmp-* $(srcdir)/aclocal.m4 $(srcdir)/configure \
136 $(srcdir)/src/config.in
137 -[ "$(srcdir)" = "." ] || \
138 find $(srcdir) '(' -name '*~' -o -name '#*' ')' $(FIND_DELETE)
139 -find . '(' -name '*~' -o -name '#*' ')' $(FIND_DELETE)
140bootstrap-clean: extraclean
diff --git a/exec/README b/exec/README
new file mode 100644
index 00000000000..f7eb21cfc84
--- /dev/null
+++ b/exec/README
@@ -0,0 +1,3 @@
1This directory holds the source code to a library used to replace the
2`execve' and `execveat' system calls, used by the Android port of
3Emacs to start executables without intervention from the system.
diff --git a/exec/config-mips.m4.in b/exec/config-mips.m4.in
new file mode 100644
index 00000000000..72632765bd0
--- /dev/null
+++ b/exec/config-mips.m4.in
@@ -0,0 +1,42 @@
1dnl Assembler templates for MIPS computers.
2dnl
3dnl Copyright (C) 2023 Free Software Foundation, Inc.
4dnl
5dnl This file is part of GNU Emacs.
6dnl
7dnl GNU Emacs is free software: you can redistribute it and/or modify
8dnl it under the terms of the GNU General Public License as published by
9dnl the Free Software Foundation, either version 3 of the License, or
10dnl (at your option) any later version.
11dnl
12dnl GNU Emacs is distributed in the hope that it will be useful,
13dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
14dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15dnl GNU General Public License for more details.
16dnl
17dnl You should have received a copy of the GNU General Public License
18dnl along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20define(`SYSCALL_open', `ifelse(`@MIPS_N32@',`yes',`6002',`4005')')
21define(`SYSCALL_close', `ifelse(`@MIPS_N32@',`yes',`6003',`4006')')
22define(`SYSCALL_mmap', `ifelse(`@MIPS_N32@',`yes',`6009',`4090')')
23define(`SYSCALL_nanosleep', `ifelse(`@MIPS_N32@',`yes',`6034',`4166')')
24define(`SYSCALL_exit', `ifelse(`@MIPS_N32@',`yes',`6058',`4001')')
25define(`SYSCALL_prctl', `ifelse(`@MIPS_N32@',`yes',`6153',`4192')')
26
27define(`SYSCALL', `ifelse(`@MIPS_N32@',`yes',` move $a4, $1
28 move $a5, $2
29 move $a6, $3
30 move $a7, $4',` addi $sp, -32
31 sw $1, 16($sp)
32 sw $2, 20($sp)
33 sw $3, 24($sp)
34 sw $4, 28($sp)')')
35
36define(`RESTORE', `ifelse(`@MIPS_N32@',`yes',` nop',` addi $sp, 32')')
37
38dnl For mips64. Some assemblers don't want to assemble `daddi'.
39define(`DADDI2', `ifelse(`@DADDI_BROKEN@',`yes',` li $at, $2
40dadd $1, $1, $at',` daddi $1, $2')')
41define(`DADDI3', `ifelse(`@DADDI_BROKEN@',`yes',` li $at, $3
42dadd $1, $2, $at',` daddi $1, $2, $3')')
diff --git a/exec/config.guess b/exec/config.guess
new file mode 100755
index 00000000000..c7f17e8fb97
--- /dev/null
+++ b/exec/config.guess
@@ -0,0 +1,1768 @@
1#!/usr/bin/sh
2# Attempt to guess a canonical system name.
3# Copyright 1992-2022 Free Software Foundation, Inc.
4
5# shellcheck disable=SC2006,SC2268 # see below for rationale
6
7timestamp='2022-05-25'
8
9# This file is free software; you can redistribute it and/or modify it
10# under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful, but
15# WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17# General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, see <https://www.gnu.org/licenses/>.
21#
22# As a special exception to the GNU General Public License, if you
23# distribute this file as part of a program that contains a
24# configuration script generated by Autoconf, you may include it under
25# the same distribution terms that you use for the rest of that
26# program. This Exception is an additional permission under section 7
27# of the GNU General Public License, version 3 ("GPLv3").
28#
29# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
30#
31# You can get the latest version of this script from:
32# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
33#
34# Please send patches to <config-patches@gnu.org>.
35
36
37# The "shellcheck disable" line above the timestamp inhibits complaints
38# about features and limitations of the classic Bourne shell that were
39# superseded or lifted in POSIX. However, this script identifies a wide
40# variety of pre-POSIX systems that do not have POSIX shells at all, and
41# even some reasonably current systems (Solaris 10 as case-in-point) still
42# have a pre-POSIX /bin/sh.
43
44
45me=`echo "$0" | sed -e 's,.*/,,'`
46
47usage="\
48Usage: $0 [OPTION]
49
50Output the configuration name of the system \`$me' is run on.
51
52Options:
53 -h, --help print this help, then exit
54 -t, --time-stamp print date of last modification, then exit
55 -v, --version print version number, then exit
56
57Report bugs and patches to <config-patches@gnu.org>."
58
59version="\
60GNU config.guess ($timestamp)
61
62Originally written by Per Bothner.
63Copyright 1992-2022 Free Software Foundation, Inc.
64
65This is free software; see the source for copying conditions. There is NO
66warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
67
68help="
69Try \`$me --help' for more information."
70
71# Parse command line
72while test $# -gt 0 ; do
73 case $1 in
74 --time-stamp | --time* | -t )
75 echo "$timestamp" ; exit ;;
76 --version | -v )
77 echo "$version" ; exit ;;
78 --help | --h* | -h )
79 echo "$usage"; exit ;;
80 -- ) # Stop option processing
81 shift; break ;;
82 - ) # Use stdin as input.
83 break ;;
84 -* )
85 echo "$me: invalid option $1$help" >&2
86 exit 1 ;;
87 * )
88 break ;;
89 esac
90done
91
92if test $# != 0; then
93 echo "$me: too many arguments$help" >&2
94 exit 1
95fi
96
97# Just in case it came from the environment.
98GUESS=
99
100# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
101# compiler to aid in system detection is discouraged as it requires
102# temporary files to be created and, as you can see below, it is a
103# headache to deal with in a portable fashion.
104
105# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
106# use `HOST_CC' if defined, but it is deprecated.
107
108# Portable tmp directory creation inspired by the Autoconf team.
109
110tmp=
111# shellcheck disable=SC2172
112trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
113
114set_cc_for_build() {
115 # prevent multiple calls if $tmp is already set
116 test "$tmp" && return 0
117 : "${TMPDIR=/tmp}"
118 # shellcheck disable=SC2039,SC3028
119 { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
120 { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
121 { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
122 { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
123 dummy=$tmp/dummy
124 case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
125 ,,) echo "int x;" > "$dummy.c"
126 for driver in cc gcc c89 c99 ; do
127 if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
128 CC_FOR_BUILD=$driver
129 break
130 fi
131 done
132 if test x"$CC_FOR_BUILD" = x ; then
133 CC_FOR_BUILD=no_compiler_found
134 fi
135 ;;
136 ,,*) CC_FOR_BUILD=$CC ;;
137 ,*,*) CC_FOR_BUILD=$HOST_CC ;;
138 esac
139}
140
141# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
142# (ghazi@noc.rutgers.edu 1994-08-24)
143if test -f /.attbin/uname ; then
144 PATH=$PATH:/.attbin ; export PATH
145fi
146
147UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
148UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
149UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
150UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
151
152case $UNAME_SYSTEM in
153Linux|GNU|GNU/*)
154 LIBC=unknown
155
156 set_cc_for_build
157 cat <<-EOF > "$dummy.c"
158 #include <features.h>
159 #if defined(__UCLIBC__)
160 LIBC=uclibc
161 #elif defined(__dietlibc__)
162 LIBC=dietlibc
163 #elif defined(__GLIBC__)
164 LIBC=gnu
165 #else
166 #include <stdarg.h>
167 /* First heuristic to detect musl libc. */
168 #ifdef __DEFINED_va_list
169 LIBC=musl
170 #endif
171 #endif
172 EOF
173 cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
174 eval "$cc_set_libc"
175
176 # Second heuristic to detect musl libc.
177 if [ "$LIBC" = unknown ] &&
178 command -v ldd >/dev/null &&
179 ldd --version 2>&1 | grep -q ^musl; then
180 LIBC=musl
181 fi
182
183 # If the system lacks a compiler, then just pick glibc.
184 # We could probably try harder.
185 if [ "$LIBC" = unknown ]; then
186 LIBC=gnu
187 fi
188 ;;
189esac
190
191# Note: order is significant - the case branches are not exclusive.
192
193case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
194 *:NetBSD:*:*)
195 # NetBSD (nbsd) targets should (where applicable) match one or
196 # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
197 # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
198 # switched to ELF, *-*-netbsd* would select the old
199 # object file format. This provides both forward
200 # compatibility and a consistent mechanism for selecting the
201 # object file format.
202 #
203 # Note: NetBSD doesn't particularly care about the vendor
204 # portion of the name. We always set it to "unknown".
205 UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
206 /sbin/sysctl -n hw.machine_arch 2>/dev/null || \
207 /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
208 echo unknown)`
209 case $UNAME_MACHINE_ARCH in
210 aarch64eb) machine=aarch64_be-unknown ;;
211 armeb) machine=armeb-unknown ;;
212 arm*) machine=arm-unknown ;;
213 sh3el) machine=shl-unknown ;;
214 sh3eb) machine=sh-unknown ;;
215 sh5el) machine=sh5le-unknown ;;
216 earmv*)
217 arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
218 endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
219 machine=${arch}${endian}-unknown
220 ;;
221 *) machine=$UNAME_MACHINE_ARCH-unknown ;;
222 esac
223 # The Operating System including object format, if it has switched
224 # to ELF recently (or will in the future) and ABI.
225 case $UNAME_MACHINE_ARCH in
226 earm*)
227 os=netbsdelf
228 ;;
229 arm*|i386|m68k|ns32k|sh3*|sparc|vax)
230 set_cc_for_build
231 if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
232 | grep -q __ELF__
233 then
234 # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
235 # Return netbsd for either. FIX?
236 os=netbsd
237 else
238 os=netbsdelf
239 fi
240 ;;
241 *)
242 os=netbsd
243 ;;
244 esac
245 # Determine ABI tags.
246 case $UNAME_MACHINE_ARCH in
247 earm*)
248 expr='s/^earmv[0-9]/-eabi/;s/eb$//'
249 abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
250 ;;
251 esac
252 # The OS release
253 # Debian GNU/NetBSD machines have a different userland, and
254 # thus, need a distinct triplet. However, they do not need
255 # kernel version information, so it can be replaced with a
256 # suitable tag, in the style of linux-gnu.
257 case $UNAME_VERSION in
258 Debian*)
259 release='-gnu'
260 ;;
261 *)
262 release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
263 ;;
264 esac
265 # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
266 # contains redundant information, the shorter form:
267 # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
268 GUESS=$machine-${os}${release}${abi-}
269 ;;
270 *:Bitrig:*:*)
271 UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
272 GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE
273 ;;
274 *:OpenBSD:*:*)
275 UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
276 GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE
277 ;;
278 *:SecBSD:*:*)
279 UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'`
280 GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE
281 ;;
282 *:LibertyBSD:*:*)
283 UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
284 GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE
285 ;;
286 *:MidnightBSD:*:*)
287 GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE
288 ;;
289 *:ekkoBSD:*:*)
290 GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE
291 ;;
292 *:SolidBSD:*:*)
293 GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE
294 ;;
295 *:OS108:*:*)
296 GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE
297 ;;
298 macppc:MirBSD:*:*)
299 GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE
300 ;;
301 *:MirBSD:*:*)
302 GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE
303 ;;
304 *:Sortix:*:*)
305 GUESS=$UNAME_MACHINE-unknown-sortix
306 ;;
307 *:Twizzler:*:*)
308 GUESS=$UNAME_MACHINE-unknown-twizzler
309 ;;
310 *:Redox:*:*)
311 GUESS=$UNAME_MACHINE-unknown-redox
312 ;;
313 mips:OSF1:*.*)
314 GUESS=mips-dec-osf1
315 ;;
316 alpha:OSF1:*:*)
317 # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
318 trap '' 0
319 case $UNAME_RELEASE in
320 *4.0)
321 UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
322 ;;
323 *5.*)
324 UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
325 ;;
326 esac
327 # According to Compaq, /usr/sbin/psrinfo has been available on
328 # OSF/1 and Tru64 systems produced since 1995. I hope that
329 # covers most systems running today. This code pipes the CPU
330 # types through head -n 1, so we only detect the type of CPU 0.
331 ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
332 case $ALPHA_CPU_TYPE in
333 "EV4 (21064)")
334 UNAME_MACHINE=alpha ;;
335 "EV4.5 (21064)")
336 UNAME_MACHINE=alpha ;;
337 "LCA4 (21066/21068)")
338 UNAME_MACHINE=alpha ;;
339 "EV5 (21164)")
340 UNAME_MACHINE=alphaev5 ;;
341 "EV5.6 (21164A)")
342 UNAME_MACHINE=alphaev56 ;;
343 "EV5.6 (21164PC)")
344 UNAME_MACHINE=alphapca56 ;;
345 "EV5.7 (21164PC)")
346 UNAME_MACHINE=alphapca57 ;;
347 "EV6 (21264)")
348 UNAME_MACHINE=alphaev6 ;;
349 "EV6.7 (21264A)")
350 UNAME_MACHINE=alphaev67 ;;
351 "EV6.8CB (21264C)")
352 UNAME_MACHINE=alphaev68 ;;
353 "EV6.8AL (21264B)")
354 UNAME_MACHINE=alphaev68 ;;
355 "EV6.8CX (21264D)")
356 UNAME_MACHINE=alphaev68 ;;
357 "EV6.9A (21264/EV69A)")
358 UNAME_MACHINE=alphaev69 ;;
359 "EV7 (21364)")
360 UNAME_MACHINE=alphaev7 ;;
361 "EV7.9 (21364A)")
362 UNAME_MACHINE=alphaev79 ;;
363 esac
364 # A Pn.n version is a patched version.
365 # A Vn.n version is a released version.
366 # A Tn.n version is a released field test version.
367 # A Xn.n version is an unreleased experimental baselevel.
368 # 1.2 uses "1.2" for uname -r.
369 OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
370 GUESS=$UNAME_MACHINE-dec-osf$OSF_REL
371 ;;
372 Amiga*:UNIX_System_V:4.0:*)
373 GUESS=m68k-unknown-sysv4
374 ;;
375 *:[Aa]miga[Oo][Ss]:*:*)
376 GUESS=$UNAME_MACHINE-unknown-amigaos
377 ;;
378 *:[Mm]orph[Oo][Ss]:*:*)
379 GUESS=$UNAME_MACHINE-unknown-morphos
380 ;;
381 *:OS/390:*:*)
382 GUESS=i370-ibm-openedition
383 ;;
384 *:z/VM:*:*)
385 GUESS=s390-ibm-zvmoe
386 ;;
387 *:OS400:*:*)
388 GUESS=powerpc-ibm-os400
389 ;;
390 arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
391 GUESS=arm-acorn-riscix$UNAME_RELEASE
392 ;;
393 arm*:riscos:*:*|arm*:RISCOS:*:*)
394 GUESS=arm-unknown-riscos
395 ;;
396 SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
397 GUESS=hppa1.1-hitachi-hiuxmpp
398 ;;
399 Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
400 # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
401 case `(/bin/universe) 2>/dev/null` in
402 att) GUESS=pyramid-pyramid-sysv3 ;;
403 *) GUESS=pyramid-pyramid-bsd ;;
404 esac
405 ;;
406 NILE*:*:*:dcosx)
407 GUESS=pyramid-pyramid-svr4
408 ;;
409 DRS?6000:unix:4.0:6*)
410 GUESS=sparc-icl-nx6
411 ;;
412 DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
413 case `/usr/bin/uname -p` in
414 sparc) GUESS=sparc-icl-nx7 ;;
415 esac
416 ;;
417 s390x:SunOS:*:*)
418 SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
419 GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL
420 ;;
421 sun4H:SunOS:5.*:*)
422 SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
423 GUESS=sparc-hal-solaris2$SUN_REL
424 ;;
425 sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
426 SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
427 GUESS=sparc-sun-solaris2$SUN_REL
428 ;;
429 i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
430 GUESS=i386-pc-auroraux$UNAME_RELEASE
431 ;;
432 i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
433 set_cc_for_build
434 SUN_ARCH=i386
435 # If there is a compiler, see if it is configured for 64-bit objects.
436 # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
437 # This test works for both compilers.
438 if test "$CC_FOR_BUILD" != no_compiler_found; then
439 if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
440 (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \
441 grep IS_64BIT_ARCH >/dev/null
442 then
443 SUN_ARCH=x86_64
444 fi
445 fi
446 SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
447 GUESS=$SUN_ARCH-pc-solaris2$SUN_REL
448 ;;
449 sun4*:SunOS:6*:*)
450 # According to config.sub, this is the proper way to canonicalize
451 # SunOS6. Hard to guess exactly what SunOS6 will be like, but
452 # it's likely to be more like Solaris than SunOS4.
453 SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
454 GUESS=sparc-sun-solaris3$SUN_REL
455 ;;
456 sun4*:SunOS:*:*)
457 case `/usr/bin/arch -k` in
458 Series*|S4*)
459 UNAME_RELEASE=`uname -v`
460 ;;
461 esac
462 # Japanese Language versions have a version number like `4.1.3-JL'.
463 SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
464 GUESS=sparc-sun-sunos$SUN_REL
465 ;;
466 sun3*:SunOS:*:*)
467 GUESS=m68k-sun-sunos$UNAME_RELEASE
468 ;;
469 sun*:*:4.2BSD:*)
470 UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
471 test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
472 case `/bin/arch` in
473 sun3)
474 GUESS=m68k-sun-sunos$UNAME_RELEASE
475 ;;
476 sun4)
477 GUESS=sparc-sun-sunos$UNAME_RELEASE
478 ;;
479 esac
480 ;;
481 aushp:SunOS:*:*)
482 GUESS=sparc-auspex-sunos$UNAME_RELEASE
483 ;;
484 # The situation for MiNT is a little confusing. The machine name
485 # can be virtually everything (everything which is not
486 # "atarist" or "atariste" at least should have a processor
487 # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
488 # to the lowercase version "mint" (or "freemint"). Finally
489 # the system name "TOS" denotes a system which is actually not
490 # MiNT. But MiNT is downward compatible to TOS, so this should
491 # be no problem.
492 atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
493 GUESS=m68k-atari-mint$UNAME_RELEASE
494 ;;
495 atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
496 GUESS=m68k-atari-mint$UNAME_RELEASE
497 ;;
498 *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
499 GUESS=m68k-atari-mint$UNAME_RELEASE
500 ;;
501 milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
502 GUESS=m68k-milan-mint$UNAME_RELEASE
503 ;;
504 hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
505 GUESS=m68k-hades-mint$UNAME_RELEASE
506 ;;
507 *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
508 GUESS=m68k-unknown-mint$UNAME_RELEASE
509 ;;
510 m68k:machten:*:*)
511 GUESS=m68k-apple-machten$UNAME_RELEASE
512 ;;
513 powerpc:machten:*:*)
514 GUESS=powerpc-apple-machten$UNAME_RELEASE
515 ;;
516 RISC*:Mach:*:*)
517 GUESS=mips-dec-mach_bsd4.3
518 ;;
519 RISC*:ULTRIX:*:*)
520 GUESS=mips-dec-ultrix$UNAME_RELEASE
521 ;;
522 VAX*:ULTRIX*:*:*)
523 GUESS=vax-dec-ultrix$UNAME_RELEASE
524 ;;
525 2020:CLIX:*:* | 2430:CLIX:*:*)
526 GUESS=clipper-intergraph-clix$UNAME_RELEASE
527 ;;
528 mips:*:*:UMIPS | mips:*:*:RISCos)
529 set_cc_for_build
530 sed 's/^ //' << EOF > "$dummy.c"
531#ifdef __cplusplus
532#include <stdio.h> /* for printf() prototype */
533 int main (int argc, char *argv[]) {
534#else
535 int main (argc, argv) int argc; char *argv[]; {
536#endif
537 #if defined (host_mips) && defined (MIPSEB)
538 #if defined (SYSTYPE_SYSV)
539 printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
540 #endif
541 #if defined (SYSTYPE_SVR4)
542 printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
543 #endif
544 #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
545 printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
546 #endif
547 #endif
548 exit (-1);
549 }
550EOF
551 $CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
552 dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
553 SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
554 { echo "$SYSTEM_NAME"; exit; }
555 GUESS=mips-mips-riscos$UNAME_RELEASE
556 ;;
557 Motorola:PowerMAX_OS:*:*)
558 GUESS=powerpc-motorola-powermax
559 ;;
560 Motorola:*:4.3:PL8-*)
561 GUESS=powerpc-harris-powermax
562 ;;
563 Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
564 GUESS=powerpc-harris-powermax
565 ;;
566 Night_Hawk:Power_UNIX:*:*)
567 GUESS=powerpc-harris-powerunix
568 ;;
569 m88k:CX/UX:7*:*)
570 GUESS=m88k-harris-cxux7
571 ;;
572 m88k:*:4*:R4*)
573 GUESS=m88k-motorola-sysv4
574 ;;
575 m88k:*:3*:R3*)
576 GUESS=m88k-motorola-sysv3
577 ;;
578 AViiON:dgux:*:*)
579 # DG/UX returns AViiON for all architectures
580 UNAME_PROCESSOR=`/usr/bin/uname -p`
581 if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
582 then
583 if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
584 test "$TARGET_BINARY_INTERFACE"x = x
585 then
586 GUESS=m88k-dg-dgux$UNAME_RELEASE
587 else
588 GUESS=m88k-dg-dguxbcs$UNAME_RELEASE
589 fi
590 else
591 GUESS=i586-dg-dgux$UNAME_RELEASE
592 fi
593 ;;
594 M88*:DolphinOS:*:*) # DolphinOS (SVR3)
595 GUESS=m88k-dolphin-sysv3
596 ;;
597 M88*:*:R3*:*)
598 # Delta 88k system running SVR3
599 GUESS=m88k-motorola-sysv3
600 ;;
601 XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
602 GUESS=m88k-tektronix-sysv3
603 ;;
604 Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
605 GUESS=m68k-tektronix-bsd
606 ;;
607 *:IRIX*:*:*)
608 IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'`
609 GUESS=mips-sgi-irix$IRIX_REL
610 ;;
611 ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
612 GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id
613 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
614 i*86:AIX:*:*)
615 GUESS=i386-ibm-aix
616 ;;
617 ia64:AIX:*:*)
618 if test -x /usr/bin/oslevel ; then
619 IBM_REV=`/usr/bin/oslevel`
620 else
621 IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
622 fi
623 GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV
624 ;;
625 *:AIX:2:3)
626 if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
627 set_cc_for_build
628 sed 's/^ //' << EOF > "$dummy.c"
629 #include <sys/systemcfg.h>
630
631 main()
632 {
633 if (!__power_pc())
634 exit(1);
635 puts("powerpc-ibm-aix3.2.5");
636 exit(0);
637 }
638EOF
639 if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
640 then
641 GUESS=$SYSTEM_NAME
642 else
643 GUESS=rs6000-ibm-aix3.2.5
644 fi
645 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
646 GUESS=rs6000-ibm-aix3.2.4
647 else
648 GUESS=rs6000-ibm-aix3.2
649 fi
650 ;;
651 *:AIX:*:[4567])
652 IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
653 if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
654 IBM_ARCH=rs6000
655 else
656 IBM_ARCH=powerpc
657 fi
658 if test -x /usr/bin/lslpp ; then
659 IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \
660 awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
661 else
662 IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
663 fi
664 GUESS=$IBM_ARCH-ibm-aix$IBM_REV
665 ;;
666 *:AIX:*:*)
667 GUESS=rs6000-ibm-aix
668 ;;
669 ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
670 GUESS=romp-ibm-bsd4.4
671 ;;
672 ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
673 GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to
674 ;; # report: romp-ibm BSD 4.3
675 *:BOSX:*:*)
676 GUESS=rs6000-bull-bosx
677 ;;
678 DPX/2?00:B.O.S.:*:*)
679 GUESS=m68k-bull-sysv3
680 ;;
681 9000/[34]??:4.3bsd:1.*:*)
682 GUESS=m68k-hp-bsd
683 ;;
684 hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
685 GUESS=m68k-hp-bsd4.4
686 ;;
687 9000/[34678]??:HP-UX:*:*)
688 HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
689 case $UNAME_MACHINE in
690 9000/31?) HP_ARCH=m68000 ;;
691 9000/[34]??) HP_ARCH=m68k ;;
692 9000/[678][0-9][0-9])
693 if test -x /usr/bin/getconf; then
694 sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
695 sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
696 case $sc_cpu_version in
697 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
698 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
699 532) # CPU_PA_RISC2_0
700 case $sc_kernel_bits in
701 32) HP_ARCH=hppa2.0n ;;
702 64) HP_ARCH=hppa2.0w ;;
703 '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
704 esac ;;
705 esac
706 fi
707 if test "$HP_ARCH" = ""; then
708 set_cc_for_build
709 sed 's/^ //' << EOF > "$dummy.c"
710
711 #define _HPUX_SOURCE
712 #include <stdlib.h>
713 #include <unistd.h>
714
715 int main ()
716 {
717 #if defined(_SC_KERNEL_BITS)
718 long bits = sysconf(_SC_KERNEL_BITS);
719 #endif
720 long cpu = sysconf (_SC_CPU_VERSION);
721
722 switch (cpu)
723 {
724 case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
725 case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
726 case CPU_PA_RISC2_0:
727 #if defined(_SC_KERNEL_BITS)
728 switch (bits)
729 {
730 case 64: puts ("hppa2.0w"); break;
731 case 32: puts ("hppa2.0n"); break;
732 default: puts ("hppa2.0"); break;
733 } break;
734 #else /* !defined(_SC_KERNEL_BITS) */
735 puts ("hppa2.0"); break;
736 #endif
737 default: puts ("hppa1.0"); break;
738 }
739 exit (0);
740 }
741EOF
742 (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
743 test -z "$HP_ARCH" && HP_ARCH=hppa
744 fi ;;
745 esac
746 if test "$HP_ARCH" = hppa2.0w
747 then
748 set_cc_for_build
749
750 # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
751 # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
752 # generating 64-bit code. GNU and HP use different nomenclature:
753 #
754 # $ CC_FOR_BUILD=cc ./config.guess
755 # => hppa2.0w-hp-hpux11.23
756 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
757 # => hppa64-hp-hpux11.23
758
759 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
760 grep -q __LP64__
761 then
762 HP_ARCH=hppa2.0w
763 else
764 HP_ARCH=hppa64
765 fi
766 fi
767 GUESS=$HP_ARCH-hp-hpux$HPUX_REV
768 ;;
769 ia64:HP-UX:*:*)
770 HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
771 GUESS=ia64-hp-hpux$HPUX_REV
772 ;;
773 3050*:HI-UX:*:*)
774 set_cc_for_build
775 sed 's/^ //' << EOF > "$dummy.c"
776 #include <unistd.h>
777 int
778 main ()
779 {
780 long cpu = sysconf (_SC_CPU_VERSION);
781 /* The order matters, because CPU_IS_HP_MC68K erroneously returns
782 true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
783 results, however. */
784 if (CPU_IS_PA_RISC (cpu))
785 {
786 switch (cpu)
787 {
788 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
789 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
790 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
791 default: puts ("hppa-hitachi-hiuxwe2"); break;
792 }
793 }
794 else if (CPU_IS_HP_MC68K (cpu))
795 puts ("m68k-hitachi-hiuxwe2");
796 else puts ("unknown-hitachi-hiuxwe2");
797 exit (0);
798 }
799EOF
800 $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
801 { echo "$SYSTEM_NAME"; exit; }
802 GUESS=unknown-hitachi-hiuxwe2
803 ;;
804 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
805 GUESS=hppa1.1-hp-bsd
806 ;;
807 9000/8??:4.3bsd:*:*)
808 GUESS=hppa1.0-hp-bsd
809 ;;
810 *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
811 GUESS=hppa1.0-hp-mpeix
812 ;;
813 hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
814 GUESS=hppa1.1-hp-osf
815 ;;
816 hp8??:OSF1:*:*)
817 GUESS=hppa1.0-hp-osf
818 ;;
819 i*86:OSF1:*:*)
820 if test -x /usr/sbin/sysversion ; then
821 GUESS=$UNAME_MACHINE-unknown-osf1mk
822 else
823 GUESS=$UNAME_MACHINE-unknown-osf1
824 fi
825 ;;
826 parisc*:Lites*:*:*)
827 GUESS=hppa1.1-hp-lites
828 ;;
829 C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
830 GUESS=c1-convex-bsd
831 ;;
832 C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
833 if getsysinfo -f scalar_acc
834 then echo c32-convex-bsd
835 else echo c2-convex-bsd
836 fi
837 exit ;;
838 C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
839 GUESS=c34-convex-bsd
840 ;;
841 C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
842 GUESS=c38-convex-bsd
843 ;;
844 C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
845 GUESS=c4-convex-bsd
846 ;;
847 CRAY*Y-MP:*:*:*)
848 CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
849 GUESS=ymp-cray-unicos$CRAY_REL
850 ;;
851 CRAY*[A-Z]90:*:*:*)
852 echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
853 | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
854 -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
855 -e 's/\.[^.]*$/.X/'
856 exit ;;
857 CRAY*TS:*:*:*)
858 CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
859 GUESS=t90-cray-unicos$CRAY_REL
860 ;;
861 CRAY*T3E:*:*:*)
862 CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
863 GUESS=alphaev5-cray-unicosmk$CRAY_REL
864 ;;
865 CRAY*SV1:*:*:*)
866 CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
867 GUESS=sv1-cray-unicos$CRAY_REL
868 ;;
869 *:UNICOS/mp:*:*)
870 CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
871 GUESS=craynv-cray-unicosmp$CRAY_REL
872 ;;
873 F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
874 FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
875 FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
876 FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
877 GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
878 ;;
879 5000:UNIX_System_V:4.*:*)
880 FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
881 FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
882 GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
883 ;;
884 i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
885 GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE
886 ;;
887 sparc*:BSD/OS:*:*)
888 GUESS=sparc-unknown-bsdi$UNAME_RELEASE
889 ;;
890 *:BSD/OS:*:*)
891 GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE
892 ;;
893 arm:FreeBSD:*:*)
894 UNAME_PROCESSOR=`uname -p`
895 set_cc_for_build
896 if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
897 | grep -q __ARM_PCS_VFP
898 then
899 FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
900 GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi
901 else
902 FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
903 GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf
904 fi
905 ;;
906 *:FreeBSD:*:*)
907 UNAME_PROCESSOR=`/usr/bin/uname -p`
908 case $UNAME_PROCESSOR in
909 amd64)
910 UNAME_PROCESSOR=x86_64 ;;
911 i386)
912 UNAME_PROCESSOR=i586 ;;
913 esac
914 FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
915 GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL
916 ;;
917 i*:CYGWIN*:*)
918 GUESS=$UNAME_MACHINE-pc-cygwin
919 ;;
920 *:MINGW64*:*)
921 GUESS=$UNAME_MACHINE-pc-mingw64
922 ;;
923 *:MINGW*:*)
924 GUESS=$UNAME_MACHINE-pc-mingw32
925 ;;
926 *:MSYS*:*)
927 GUESS=$UNAME_MACHINE-pc-msys
928 ;;
929 i*:PW*:*)
930 GUESS=$UNAME_MACHINE-pc-pw32
931 ;;
932 *:SerenityOS:*:*)
933 GUESS=$UNAME_MACHINE-pc-serenity
934 ;;
935 *:Interix*:*)
936 case $UNAME_MACHINE in
937 x86)
938 GUESS=i586-pc-interix$UNAME_RELEASE
939 ;;
940 authenticamd | genuineintel | EM64T)
941 GUESS=x86_64-unknown-interix$UNAME_RELEASE
942 ;;
943 IA64)
944 GUESS=ia64-unknown-interix$UNAME_RELEASE
945 ;;
946 esac ;;
947 i*:UWIN*:*)
948 GUESS=$UNAME_MACHINE-pc-uwin
949 ;;
950 amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
951 GUESS=x86_64-pc-cygwin
952 ;;
953 prep*:SunOS:5.*:*)
954 SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
955 GUESS=powerpcle-unknown-solaris2$SUN_REL
956 ;;
957 *:GNU:*:*)
958 # the GNU system
959 GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'`
960 GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'`
961 GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL
962 ;;
963 *:GNU/*:*:*)
964 # other systems with GNU libc and userland
965 GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"`
966 GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
967 GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
968 ;;
969 *:Minix:*:*)
970 GUESS=$UNAME_MACHINE-unknown-minix
971 ;;
972 aarch64:Linux:*:*)
973 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
974 ;;
975 aarch64_be:Linux:*:*)
976 UNAME_MACHINE=aarch64_be
977 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
978 ;;
979 alpha:Linux:*:*)
980 case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
981 EV5) UNAME_MACHINE=alphaev5 ;;
982 EV56) UNAME_MACHINE=alphaev56 ;;
983 PCA56) UNAME_MACHINE=alphapca56 ;;
984 PCA57) UNAME_MACHINE=alphapca56 ;;
985 EV6) UNAME_MACHINE=alphaev6 ;;
986 EV67) UNAME_MACHINE=alphaev67 ;;
987 EV68*) UNAME_MACHINE=alphaev68 ;;
988 esac
989 objdump --private-headers /bin/sh | grep -q ld.so.1
990 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
991 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
992 ;;
993 arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*)
994 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
995 ;;
996 arm*:Linux:*:*)
997 set_cc_for_build
998 if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
999 | grep -q __ARM_EABI__
1000 then
1001 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1002 else
1003 if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
1004 | grep -q __ARM_PCS_VFP
1005 then
1006 GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi
1007 else
1008 GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf
1009 fi
1010 fi
1011 ;;
1012 avr32*:Linux:*:*)
1013 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1014 ;;
1015 cris:Linux:*:*)
1016 GUESS=$UNAME_MACHINE-axis-linux-$LIBC
1017 ;;
1018 crisv32:Linux:*:*)
1019 GUESS=$UNAME_MACHINE-axis-linux-$LIBC
1020 ;;
1021 e2k:Linux:*:*)
1022 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1023 ;;
1024 frv:Linux:*:*)
1025 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1026 ;;
1027 hexagon:Linux:*:*)
1028 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1029 ;;
1030 i*86:Linux:*:*)
1031 GUESS=$UNAME_MACHINE-pc-linux-$LIBC
1032 ;;
1033 ia64:Linux:*:*)
1034 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1035 ;;
1036 k1om:Linux:*:*)
1037 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1038 ;;
1039 loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
1040 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1041 ;;
1042 m32r*:Linux:*:*)
1043 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1044 ;;
1045 m68*:Linux:*:*)
1046 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1047 ;;
1048 mips:Linux:*:* | mips64:Linux:*:*)
1049 set_cc_for_build
1050 IS_GLIBC=0
1051 test x"${LIBC}" = xgnu && IS_GLIBC=1
1052 sed 's/^ //' << EOF > "$dummy.c"
1053 #undef CPU
1054 #undef mips
1055 #undef mipsel
1056 #undef mips64
1057 #undef mips64el
1058 #if ${IS_GLIBC} && defined(_ABI64)
1059 LIBCABI=gnuabi64
1060 #else
1061 #if ${IS_GLIBC} && defined(_ABIN32)
1062 LIBCABI=gnuabin32
1063 #else
1064 LIBCABI=${LIBC}
1065 #endif
1066 #endif
1067
1068 #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
1069 CPU=mipsisa64r6
1070 #else
1071 #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
1072 CPU=mipsisa32r6
1073 #else
1074 #if defined(__mips64)
1075 CPU=mips64
1076 #else
1077 CPU=mips
1078 #endif
1079 #endif
1080 #endif
1081
1082 #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
1083 MIPS_ENDIAN=el
1084 #else
1085 #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
1086 MIPS_ENDIAN=
1087 #else
1088 MIPS_ENDIAN=
1089 #endif
1090 #endif
1091EOF
1092 cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`
1093 eval "$cc_set_vars"
1094 test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
1095 ;;
1096 mips64el:Linux:*:*)
1097 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1098 ;;
1099 openrisc*:Linux:*:*)
1100 GUESS=or1k-unknown-linux-$LIBC
1101 ;;
1102 or32:Linux:*:* | or1k*:Linux:*:*)
1103 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1104 ;;
1105 padre:Linux:*:*)
1106 GUESS=sparc-unknown-linux-$LIBC
1107 ;;
1108 parisc64:Linux:*:* | hppa64:Linux:*:*)
1109 GUESS=hppa64-unknown-linux-$LIBC
1110 ;;
1111 parisc:Linux:*:* | hppa:Linux:*:*)
1112 # Look for CPU level
1113 case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
1114 PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;;
1115 PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;;
1116 *) GUESS=hppa-unknown-linux-$LIBC ;;
1117 esac
1118 ;;
1119 ppc64:Linux:*:*)
1120 GUESS=powerpc64-unknown-linux-$LIBC
1121 ;;
1122 ppc:Linux:*:*)
1123 GUESS=powerpc-unknown-linux-$LIBC
1124 ;;
1125 ppc64le:Linux:*:*)
1126 GUESS=powerpc64le-unknown-linux-$LIBC
1127 ;;
1128 ppcle:Linux:*:*)
1129 GUESS=powerpcle-unknown-linux-$LIBC
1130 ;;
1131 riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
1132 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1133 ;;
1134 s390:Linux:*:* | s390x:Linux:*:*)
1135 GUESS=$UNAME_MACHINE-ibm-linux-$LIBC
1136 ;;
1137 sh64*:Linux:*:*)
1138 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1139 ;;
1140 sh*:Linux:*:*)
1141 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1142 ;;
1143 sparc:Linux:*:* | sparc64:Linux:*:*)
1144 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1145 ;;
1146 tile*:Linux:*:*)
1147 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1148 ;;
1149 vax:Linux:*:*)
1150 GUESS=$UNAME_MACHINE-dec-linux-$LIBC
1151 ;;
1152 x86_64:Linux:*:*)
1153 set_cc_for_build
1154 CPU=$UNAME_MACHINE
1155 LIBCABI=$LIBC
1156 if test "$CC_FOR_BUILD" != no_compiler_found; then
1157 ABI=64
1158 sed 's/^ //' << EOF > "$dummy.c"
1159 #ifdef __i386__
1160 ABI=x86
1161 #else
1162 #ifdef __ILP32__
1163 ABI=x32
1164 #endif
1165 #endif
1166EOF
1167 cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
1168 eval "$cc_set_abi"
1169 case $ABI in
1170 x86) CPU=i686 ;;
1171 x32) LIBCABI=${LIBC}x32 ;;
1172 esac
1173 fi
1174 GUESS=$CPU-pc-linux-$LIBCABI
1175 ;;
1176 xtensa*:Linux:*:*)
1177 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
1178 ;;
1179 i*86:DYNIX/ptx:4*:*)
1180 # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
1181 # earlier versions are messed up and put the nodename in both
1182 # sysname and nodename.
1183 GUESS=i386-sequent-sysv4
1184 ;;
1185 i*86:UNIX_SV:4.2MP:2.*)
1186 # Unixware is an offshoot of SVR4, but it has its own version
1187 # number series starting with 2...
1188 # I am not positive that other SVR4 systems won't match this,
1189 # I just have to hope. -- rms.
1190 # Use sysv4.2uw... so that sysv4* matches it.
1191 GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
1192 ;;
1193 i*86:OS/2:*:*)
1194 # If we were able to find `uname', then EMX Unix compatibility
1195 # is probably installed.
1196 GUESS=$UNAME_MACHINE-pc-os2-emx
1197 ;;
1198 i*86:XTS-300:*:STOP)
1199 GUESS=$UNAME_MACHINE-unknown-stop
1200 ;;
1201 i*86:atheos:*:*)
1202 GUESS=$UNAME_MACHINE-unknown-atheos
1203 ;;
1204 i*86:syllable:*:*)
1205 GUESS=$UNAME_MACHINE-pc-syllable
1206 ;;
1207 i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
1208 GUESS=i386-unknown-lynxos$UNAME_RELEASE
1209 ;;
1210 i*86:*DOS:*:*)
1211 GUESS=$UNAME_MACHINE-pc-msdosdjgpp
1212 ;;
1213 i*86:*:4.*:*)
1214 UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
1215 if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
1216 GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL
1217 else
1218 GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL
1219 fi
1220 ;;
1221 i*86:*:5:[678]*)
1222 # UnixWare 7.x, OpenUNIX and OpenServer 6.
1223 case `/bin/uname -X | grep "^Machine"` in
1224 *486*) UNAME_MACHINE=i486 ;;
1225 *Pentium) UNAME_MACHINE=i586 ;;
1226 *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
1227 esac
1228 GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
1229 ;;
1230 i*86:*:3.2:*)
1231 if test -f /usr/options/cb.name; then
1232 UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
1233 GUESS=$UNAME_MACHINE-pc-isc$UNAME_REL
1234 elif /bin/uname -X 2>/dev/null >/dev/null ; then
1235 UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
1236 (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
1237 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
1238 && UNAME_MACHINE=i586
1239 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
1240 && UNAME_MACHINE=i686
1241 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
1242 && UNAME_MACHINE=i686
1243 GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL
1244 else
1245 GUESS=$UNAME_MACHINE-pc-sysv32
1246 fi
1247 ;;
1248 pc:*:*:*)
1249 # Left here for compatibility:
1250 # uname -m prints for DJGPP always 'pc', but it prints nothing about
1251 # the processor, so we play safe by assuming i586.
1252 # Note: whatever this is, it MUST be the same as what config.sub
1253 # prints for the "djgpp" host, or else GDB configure will decide that
1254 # this is a cross-build.
1255 GUESS=i586-pc-msdosdjgpp
1256 ;;
1257 Intel:Mach:3*:*)
1258 GUESS=i386-pc-mach3
1259 ;;
1260 paragon:*:*:*)
1261 GUESS=i860-intel-osf1
1262 ;;
1263 i860:*:4.*:*) # i860-SVR4
1264 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
1265 GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4
1266 else # Add other i860-SVR4 vendors below as they are discovered.
1267 GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4
1268 fi
1269 ;;
1270 mini*:CTIX:SYS*5:*)
1271 # "miniframe"
1272 GUESS=m68010-convergent-sysv
1273 ;;
1274 mc68k:UNIX:SYSTEM5:3.51m)
1275 GUESS=m68k-convergent-sysv
1276 ;;
1277 M680?0:D-NIX:5.3:*)
1278 GUESS=m68k-diab-dnix
1279 ;;
1280 M68*:*:R3V[5678]*:*)
1281 test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
1282 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
1283 OS_REL=''
1284 test -r /etc/.relid \
1285 && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
1286 /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
1287 && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
1288 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
1289 && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
1290 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
1291 /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
1292 && { echo i486-ncr-sysv4; exit; } ;;
1293 NCR*:*:4.2:* | MPRAS*:*:4.2:*)
1294 OS_REL='.3'
1295 test -r /etc/.relid \
1296 && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
1297 /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
1298 && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
1299 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
1300 && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
1301 /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
1302 && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
1303 m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
1304 GUESS=m68k-unknown-lynxos$UNAME_RELEASE
1305 ;;
1306 mc68030:UNIX_System_V:4.*:*)
1307 GUESS=m68k-atari-sysv4
1308 ;;
1309 TSUNAMI:LynxOS:2.*:*)
1310 GUESS=sparc-unknown-lynxos$UNAME_RELEASE
1311 ;;
1312 rs6000:LynxOS:2.*:*)
1313 GUESS=rs6000-unknown-lynxos$UNAME_RELEASE
1314 ;;
1315 PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
1316 GUESS=powerpc-unknown-lynxos$UNAME_RELEASE
1317 ;;
1318 SM[BE]S:UNIX_SV:*:*)
1319 GUESS=mips-dde-sysv$UNAME_RELEASE
1320 ;;
1321 RM*:ReliantUNIX-*:*:*)
1322 GUESS=mips-sni-sysv4
1323 ;;
1324 RM*:SINIX-*:*:*)
1325 GUESS=mips-sni-sysv4
1326 ;;
1327 *:SINIX-*:*:*)
1328 if uname -p 2>/dev/null >/dev/null ; then
1329 UNAME_MACHINE=`(uname -p) 2>/dev/null`
1330 GUESS=$UNAME_MACHINE-sni-sysv4
1331 else
1332 GUESS=ns32k-sni-sysv
1333 fi
1334 ;;
1335 PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
1336 # says <Richard.M.Bartel@ccMail.Census.GOV>
1337 GUESS=i586-unisys-sysv4
1338 ;;
1339 *:UNIX_System_V:4*:FTX*)
1340 # From Gerald Hewes <hewes@openmarket.com>.
1341 # How about differentiating between stratus architectures? -djm
1342 GUESS=hppa1.1-stratus-sysv4
1343 ;;
1344 *:*:*:FTX*)
1345 # From seanf@swdc.stratus.com.
1346 GUESS=i860-stratus-sysv4
1347 ;;
1348 i*86:VOS:*:*)
1349 # From Paul.Green@stratus.com.
1350 GUESS=$UNAME_MACHINE-stratus-vos
1351 ;;
1352 *:VOS:*:*)
1353 # From Paul.Green@stratus.com.
1354 GUESS=hppa1.1-stratus-vos
1355 ;;
1356 mc68*:A/UX:*:*)
1357 GUESS=m68k-apple-aux$UNAME_RELEASE
1358 ;;
1359 news*:NEWS-OS:6*:*)
1360 GUESS=mips-sony-newsos6
1361 ;;
1362 R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
1363 if test -d /usr/nec; then
1364 GUESS=mips-nec-sysv$UNAME_RELEASE
1365 else
1366 GUESS=mips-unknown-sysv$UNAME_RELEASE
1367 fi
1368 ;;
1369 BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
1370 GUESS=powerpc-be-beos
1371 ;;
1372 BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
1373 GUESS=powerpc-apple-beos
1374 ;;
1375 BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
1376 GUESS=i586-pc-beos
1377 ;;
1378 BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
1379 GUESS=i586-pc-haiku
1380 ;;
1381 ppc:Haiku:*:*) # Haiku running on Apple PowerPC
1382 GUESS=powerpc-apple-haiku
1383 ;;
1384 *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat)
1385 GUESS=$UNAME_MACHINE-unknown-haiku
1386 ;;
1387 SX-4:SUPER-UX:*:*)
1388 GUESS=sx4-nec-superux$UNAME_RELEASE
1389 ;;
1390 SX-5:SUPER-UX:*:*)
1391 GUESS=sx5-nec-superux$UNAME_RELEASE
1392 ;;
1393 SX-6:SUPER-UX:*:*)
1394 GUESS=sx6-nec-superux$UNAME_RELEASE
1395 ;;
1396 SX-7:SUPER-UX:*:*)
1397 GUESS=sx7-nec-superux$UNAME_RELEASE
1398 ;;
1399 SX-8:SUPER-UX:*:*)
1400 GUESS=sx8-nec-superux$UNAME_RELEASE
1401 ;;
1402 SX-8R:SUPER-UX:*:*)
1403 GUESS=sx8r-nec-superux$UNAME_RELEASE
1404 ;;
1405 SX-ACE:SUPER-UX:*:*)
1406 GUESS=sxace-nec-superux$UNAME_RELEASE
1407 ;;
1408 Power*:Rhapsody:*:*)
1409 GUESS=powerpc-apple-rhapsody$UNAME_RELEASE
1410 ;;
1411 *:Rhapsody:*:*)
1412 GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE
1413 ;;
1414 arm64:Darwin:*:*)
1415 GUESS=aarch64-apple-darwin$UNAME_RELEASE
1416 ;;
1417 *:Darwin:*:*)
1418 UNAME_PROCESSOR=`uname -p`
1419 case $UNAME_PROCESSOR in
1420 unknown) UNAME_PROCESSOR=powerpc ;;
1421 esac
1422 if command -v xcode-select > /dev/null 2> /dev/null && \
1423 ! xcode-select --print-path > /dev/null 2> /dev/null ; then
1424 # Avoid executing cc if there is no toolchain installed as
1425 # cc will be a stub that puts up a graphical alert
1426 # prompting the user to install developer tools.
1427 CC_FOR_BUILD=no_compiler_found
1428 else
1429 set_cc_for_build
1430 fi
1431 if test "$CC_FOR_BUILD" != no_compiler_found; then
1432 if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
1433 (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
1434 grep IS_64BIT_ARCH >/dev/null
1435 then
1436 case $UNAME_PROCESSOR in
1437 i386) UNAME_PROCESSOR=x86_64 ;;
1438 powerpc) UNAME_PROCESSOR=powerpc64 ;;
1439 esac
1440 fi
1441 # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
1442 if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
1443 (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
1444 grep IS_PPC >/dev/null
1445 then
1446 UNAME_PROCESSOR=powerpc
1447 fi
1448 elif test "$UNAME_PROCESSOR" = i386 ; then
1449 # uname -m returns i386 or x86_64
1450 UNAME_PROCESSOR=$UNAME_MACHINE
1451 fi
1452 GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE
1453 ;;
1454 *:procnto*:*:* | *:QNX:[0123456789]*:*)
1455 UNAME_PROCESSOR=`uname -p`
1456 if test "$UNAME_PROCESSOR" = x86; then
1457 UNAME_PROCESSOR=i386
1458 UNAME_MACHINE=pc
1459 fi
1460 GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE
1461 ;;
1462 *:QNX:*:4*)
1463 GUESS=i386-pc-qnx
1464 ;;
1465 NEO-*:NONSTOP_KERNEL:*:*)
1466 GUESS=neo-tandem-nsk$UNAME_RELEASE
1467 ;;
1468 NSE-*:NONSTOP_KERNEL:*:*)
1469 GUESS=nse-tandem-nsk$UNAME_RELEASE
1470 ;;
1471 NSR-*:NONSTOP_KERNEL:*:*)
1472 GUESS=nsr-tandem-nsk$UNAME_RELEASE
1473 ;;
1474 NSV-*:NONSTOP_KERNEL:*:*)
1475 GUESS=nsv-tandem-nsk$UNAME_RELEASE
1476 ;;
1477 NSX-*:NONSTOP_KERNEL:*:*)
1478 GUESS=nsx-tandem-nsk$UNAME_RELEASE
1479 ;;
1480 *:NonStop-UX:*:*)
1481 GUESS=mips-compaq-nonstopux
1482 ;;
1483 BS2000:POSIX*:*:*)
1484 GUESS=bs2000-siemens-sysv
1485 ;;
1486 DS/*:UNIX_System_V:*:*)
1487 GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE
1488 ;;
1489 *:Plan9:*:*)
1490 # "uname -m" is not consistent, so use $cputype instead. 386
1491 # is converted to i386 for consistency with other x86
1492 # operating systems.
1493 if test "${cputype-}" = 386; then
1494 UNAME_MACHINE=i386
1495 elif test "x${cputype-}" != x; then
1496 UNAME_MACHINE=$cputype
1497 fi
1498 GUESS=$UNAME_MACHINE-unknown-plan9
1499 ;;
1500 *:TOPS-10:*:*)
1501 GUESS=pdp10-unknown-tops10
1502 ;;
1503 *:TENEX:*:*)
1504 GUESS=pdp10-unknown-tenex
1505 ;;
1506 KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
1507 GUESS=pdp10-dec-tops20
1508 ;;
1509 XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
1510 GUESS=pdp10-xkl-tops20
1511 ;;
1512 *:TOPS-20:*:*)
1513 GUESS=pdp10-unknown-tops20
1514 ;;
1515 *:ITS:*:*)
1516 GUESS=pdp10-unknown-its
1517 ;;
1518 SEI:*:*:SEIUX)
1519 GUESS=mips-sei-seiux$UNAME_RELEASE
1520 ;;
1521 *:DragonFly:*:*)
1522 DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
1523 GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL
1524 ;;
1525 *:*VMS:*:*)
1526 UNAME_MACHINE=`(uname -p) 2>/dev/null`
1527 case $UNAME_MACHINE in
1528 A*) GUESS=alpha-dec-vms ;;
1529 I*) GUESS=ia64-dec-vms ;;
1530 V*) GUESS=vax-dec-vms ;;
1531 esac ;;
1532 *:XENIX:*:SysV)
1533 GUESS=i386-pc-xenix
1534 ;;
1535 i*86:skyos:*:*)
1536 SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`
1537 GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL
1538 ;;
1539 i*86:rdos:*:*)
1540 GUESS=$UNAME_MACHINE-pc-rdos
1541 ;;
1542 i*86:Fiwix:*:*)
1543 GUESS=$UNAME_MACHINE-pc-fiwix
1544 ;;
1545 *:AROS:*:*)
1546 GUESS=$UNAME_MACHINE-unknown-aros
1547 ;;
1548 x86_64:VMkernel:*:*)
1549 GUESS=$UNAME_MACHINE-unknown-esx
1550 ;;
1551 amd64:Isilon\ OneFS:*:*)
1552 GUESS=x86_64-unknown-onefs
1553 ;;
1554 *:Unleashed:*:*)
1555 GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
1556 ;;
1557esac
1558
1559# Do we have a guess based on uname results?
1560if test "x$GUESS" != x; then
1561 echo "$GUESS"
1562 exit
1563fi
1564
1565# No uname command or uname output not recognized.
1566set_cc_for_build
1567cat > "$dummy.c" <<EOF
1568#ifdef _SEQUENT_
1569#include <sys/types.h>
1570#include <sys/utsname.h>
1571#endif
1572#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
1573#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
1574#include <signal.h>
1575#if defined(_SIZE_T_) || defined(SIGLOST)
1576#include <sys/utsname.h>
1577#endif
1578#endif
1579#endif
1580main ()
1581{
1582#if defined (sony)
1583#if defined (MIPSEB)
1584 /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
1585 I don't know.... */
1586 printf ("mips-sony-bsd\n"); exit (0);
1587#else
1588#include <sys/param.h>
1589 printf ("m68k-sony-newsos%s\n",
1590#ifdef NEWSOS4
1591 "4"
1592#else
1593 ""
1594#endif
1595 ); exit (0);
1596#endif
1597#endif
1598
1599#if defined (NeXT)
1600#if !defined (__ARCHITECTURE__)
1601#define __ARCHITECTURE__ "m68k"
1602#endif
1603 int version;
1604 version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
1605 if (version < 4)
1606 printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
1607 else
1608 printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
1609 exit (0);
1610#endif
1611
1612#if defined (MULTIMAX) || defined (n16)
1613#if defined (UMAXV)
1614 printf ("ns32k-encore-sysv\n"); exit (0);
1615#else
1616#if defined (CMU)
1617 printf ("ns32k-encore-mach\n"); exit (0);
1618#else
1619 printf ("ns32k-encore-bsd\n"); exit (0);
1620#endif
1621#endif
1622#endif
1623
1624#if defined (__386BSD__)
1625 printf ("i386-pc-bsd\n"); exit (0);
1626#endif
1627
1628#if defined (sequent)
1629#if defined (i386)
1630 printf ("i386-sequent-dynix\n"); exit (0);
1631#endif
1632#if defined (ns32000)
1633 printf ("ns32k-sequent-dynix\n"); exit (0);
1634#endif
1635#endif
1636
1637#if defined (_SEQUENT_)
1638 struct utsname un;
1639
1640 uname(&un);
1641 if (strncmp(un.version, "V2", 2) == 0) {
1642 printf ("i386-sequent-ptx2\n"); exit (0);
1643 }
1644 if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
1645 printf ("i386-sequent-ptx1\n"); exit (0);
1646 }
1647 printf ("i386-sequent-ptx\n"); exit (0);
1648#endif
1649
1650#if defined (vax)
1651#if !defined (ultrix)
1652#include <sys/param.h>
1653#if defined (BSD)
1654#if BSD == 43
1655 printf ("vax-dec-bsd4.3\n"); exit (0);
1656#else
1657#if BSD == 199006
1658 printf ("vax-dec-bsd4.3reno\n"); exit (0);
1659#else
1660 printf ("vax-dec-bsd\n"); exit (0);
1661#endif
1662#endif
1663#else
1664 printf ("vax-dec-bsd\n"); exit (0);
1665#endif
1666#else
1667#if defined(_SIZE_T_) || defined(SIGLOST)
1668 struct utsname un;
1669 uname (&un);
1670 printf ("vax-dec-ultrix%s\n", un.release); exit (0);
1671#else
1672 printf ("vax-dec-ultrix\n"); exit (0);
1673#endif
1674#endif
1675#endif
1676#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
1677#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
1678#if defined(_SIZE_T_) || defined(SIGLOST)
1679 struct utsname *un;
1680 uname (&un);
1681 printf ("mips-dec-ultrix%s\n", un.release); exit (0);
1682#else
1683 printf ("mips-dec-ultrix\n"); exit (0);
1684#endif
1685#endif
1686#endif
1687
1688#if defined (alliant) && defined (i860)
1689 printf ("i860-alliant-bsd\n"); exit (0);
1690#endif
1691
1692 exit (1);
1693}
1694EOF
1695
1696$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` &&
1697 { echo "$SYSTEM_NAME"; exit; }
1698
1699# Apollos put the system type in the environment.
1700test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
1701
1702echo "$0: unable to guess system type" >&2
1703
1704case $UNAME_MACHINE:$UNAME_SYSTEM in
1705 mips:Linux | mips64:Linux)
1706 # If we got here on MIPS GNU/Linux, output extra information.
1707 cat >&2 <<EOF
1708
1709NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
1710the system type. Please install a C compiler and try again.
1711EOF
1712 ;;
1713esac
1714
1715cat >&2 <<EOF
1716
1717This script (version $timestamp), has failed to recognize the
1718operating system you are using. If your script is old, overwrite *all*
1719copies of config.guess and config.sub with the latest versions from:
1720
1721 https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
1722and
1723 https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
1724EOF
1725
1726our_year=`echo $timestamp | sed 's,-.*,,'`
1727thisyear=`date +%Y`
1728# shellcheck disable=SC2003
1729script_age=`expr "$thisyear" - "$our_year"`
1730if test "$script_age" -lt 3 ; then
1731 cat >&2 <<EOF
1732
1733If $0 has already been updated, send the following data and any
1734information you think might be pertinent to config-patches@gnu.org to
1735provide the necessary information to handle your system.
1736
1737config.guess timestamp = $timestamp
1738
1739uname -m = `(uname -m) 2>/dev/null || echo unknown`
1740uname -r = `(uname -r) 2>/dev/null || echo unknown`
1741uname -s = `(uname -s) 2>/dev/null || echo unknown`
1742uname -v = `(uname -v) 2>/dev/null || echo unknown`
1743
1744/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
1745/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
1746
1747hostinfo = `(hostinfo) 2>/dev/null`
1748/bin/universe = `(/bin/universe) 2>/dev/null`
1749/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
1750/bin/arch = `(/bin/arch) 2>/dev/null`
1751/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
1752/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
1753
1754UNAME_MACHINE = "$UNAME_MACHINE"
1755UNAME_RELEASE = "$UNAME_RELEASE"
1756UNAME_SYSTEM = "$UNAME_SYSTEM"
1757UNAME_VERSION = "$UNAME_VERSION"
1758EOF
1759fi
1760
1761exit 1
1762
1763# Local variables:
1764# eval: (add-hook 'before-save-hook 'time-stamp)
1765# time-stamp-start: "timestamp='"
1766# time-stamp-format: "%:y-%02m-%02d"
1767# time-stamp-end: "'"
1768# End:
diff --git a/exec/config.h.in b/exec/config.h.in
new file mode 100644
index 00000000000..3e04af37f79
--- /dev/null
+++ b/exec/config.h.in
@@ -0,0 +1,358 @@
1/* config.h.in. Generated from configure.ac by autoheader. */
2
3/* Copyright (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 it
8under the terms of the GNU General Public License as published by the
9Free Software Foundation, either version 3 of the License, or (at your
10option) any later version.
11
12GNU Emacs is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15General 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/* Define to number of reserved bytes past the stack frame. */
21#undef ABI_RED_ZONE
22
23/* Define if building universal (internal helper macro) */
24#undef AC_APPLE_UNIVERSAL_BUILD
25
26/* Define to number of the `clone3' system call. */
27#undef CLONE3_SYSCALL
28
29/* Define to number of the `clone' system call. */
30#undef CLONE_SYSCALL
31
32/* Virtual address for loading PIC executables */
33#undef EXECUTABLE_BASE
34
35/* Define to 1 if the system utilizes 64-bit ELF. */
36#undef EXEC_64
37
38/* Define to number of the `exec' system call. */
39#undef EXEC_SYSCALL
40
41/* Define to 1 if you have the declaration of `stpcpy', and to 0 if you don't.
42 */
43#undef HAVE_DECL_STPCPY
44
45/* Define to 1 if you have the declaration of `stpncpy', and to 0 if you
46 don't. */
47#undef HAVE_DECL_STPNCPY
48
49/* Define to 1 if you have the `getpagesize' function. */
50#undef HAVE_GETPAGESIZE
51
52/* Define to 1 if you have the <inttypes.h> header file. */
53#undef HAVE_INTTYPES_H
54
55/* Define to 1 if you have the <minix/config.h> header file. */
56#undef HAVE_MINIX_CONFIG_H
57
58/* Define to 1 if process_vm_readv is available. */
59#undef HAVE_PROCESS_VM
60
61/* Define to 1 if `si_syscall' is a member of `siginfo_t'. */
62#undef HAVE_SIGINFO_T_SI_SYSCALL
63
64/* Define to 1 if stdbool.h conforms to C99. */
65#undef HAVE_STDBOOL_H
66
67/* Define to 1 if you have the <stdint.h> header file. */
68#undef HAVE_STDINT_H
69
70/* Define to 1 if you have the <stdio.h> header file. */
71#undef HAVE_STDIO_H
72
73/* Define to 1 if you have the <stdlib.h> header file. */
74#undef HAVE_STDLIB_H
75
76/* Define to 1 if you have the `stpcpy' function. */
77#undef HAVE_STPCPY
78
79/* Define to 1 if you have the `stpncpy' function. */
80#undef HAVE_STPNCPY
81
82/* Define to 1 if you have the <strings.h> header file. */
83#undef HAVE_STRINGS_H
84
85/* Define to 1 if you have the <string.h> header file. */
86#undef HAVE_STRING_H
87
88/* Define to 1 if you have the <sys/param.h> header file. */
89#undef HAVE_SYS_PARAM_H
90
91/* Define to 1 if you have the <sys/stat.h> header file. */
92#undef HAVE_SYS_STAT_H
93
94/* Define to 1 if you have the <sys/types.h> header file. */
95#undef HAVE_SYS_TYPES_H
96
97/* Define to 1 if you have the <sys/uio.h> header file. */
98#undef HAVE_SYS_UIO_H
99
100/* Define to 1 if the system has the type `uintptr_t'. */
101#undef HAVE_UINTPTR_T
102
103/* Define to 1 if you have the <unistd.h> header file. */
104#undef HAVE_UNISTD_H
105
106/* Define to 1 if you have the <wchar.h> header file. */
107#undef HAVE_WCHAR_H
108
109/* Define to 1 if the system has the type `_Bool'. */
110#undef HAVE__BOOL
111
112/* Virtual address for loading PIC interpreters */
113#undef INTERPRETER_BASE
114
115/* Define to 1 if MIPS NABI calling convention is being used. */
116#undef MIPS_NABI
117
118/* Define to the address where bug reports for this package should be sent. */
119#undef PACKAGE_BUGREPORT
120
121/* Define to the full name of this package. */
122#undef PACKAGE_NAME
123
124/* Define to the full name and version of this package. */
125#undef PACKAGE_STRING
126
127/* Define to the one symbol short name of this package. */
128#undef PACKAGE_TARNAME
129
130/* Define to the home page for this package. */
131#undef PACKAGE_URL
132
133/* Define to the version of this package. */
134#undef PACKAGE_VERSION
135
136/* Define to number of the `readlinkat' system call. */
137#undef READLINKAT_SYSCALL
138
139/* Define to number of the `readlink' system call. */
140#undef READLINK_SYSCALL
141
142/* Define to 1 if the library is used within a signal handler. */
143#undef REENTRANT
144
145/* Define to 1 if the stack grows downwards. */
146#undef STACK_GROWS_DOWNWARDS
147
148/* Define to register holding the stack pointer. */
149#undef STACK_POINTER
150
151/* Define to 1 if all of the C90 standard headers exist (not just the ones
152 required in a freestanding environment). This macro is provided for
153 backward compatibility; new code need not use it. */
154#undef STDC_HEADERS
155
156/* Define to register holding arg1 to system calls. */
157#undef SYSCALL_ARG1_REG
158
159/* Define to register holding arg2 to system calls. */
160#undef SYSCALL_ARG2_REG
161
162/* Define to register holding arg3 to system calls. */
163#undef SYSCALL_ARG3_REG
164
165/* Define to register holding arg0 to system calls. */
166#undef SYSCALL_ARG_REG
167
168/* Define to header holding system call numbers. */
169#undef SYSCALL_HEADER
170
171/* Define to register holding the system call number. */
172#undef SYSCALL_NUM_REG
173
174/* Define to register holding value of system calls. */
175#undef SYSCALL_RET_REG
176
177/* Define to header holding USER_REGS_STRUCT. */
178#undef USER_HEADER
179
180/* Define to structure holding user registers. */
181#undef USER_REGS_STRUCT
182
183/* Define to word type used by tracees. */
184#undef USER_WORD
185
186/* Enable extensions on AIX 3, Interix. */
187#ifndef _ALL_SOURCE
188# undef _ALL_SOURCE
189#endif
190/* Enable general extensions on macOS. */
191#ifndef _DARWIN_C_SOURCE
192# undef _DARWIN_C_SOURCE
193#endif
194/* Enable general extensions on Solaris. */
195#ifndef __EXTENSIONS__
196# undef __EXTENSIONS__
197#endif
198/* Enable GNU extensions on systems that have them. */
199#ifndef _GNU_SOURCE
200# undef _GNU_SOURCE
201#endif
202/* Enable X/Open compliant socket functions that do not require linking
203 with -lxnet on HP-UX 11.11. */
204#ifndef _HPUX_ALT_XOPEN_SOCKET_API
205# undef _HPUX_ALT_XOPEN_SOCKET_API
206#endif
207/* Identify the host operating system as Minix.
208 This macro does not affect the system headers' behavior.
209 A future release of Autoconf may stop defining this macro. */
210#ifndef _MINIX
211# undef _MINIX
212#endif
213/* Enable general extensions on NetBSD.
214 Enable NetBSD compatibility extensions on Minix. */
215#ifndef _NETBSD_SOURCE
216# undef _NETBSD_SOURCE
217#endif
218/* Enable OpenBSD compatibility extensions on NetBSD.
219 Oddly enough, this does nothing on OpenBSD. */
220#ifndef _OPENBSD_SOURCE
221# undef _OPENBSD_SOURCE
222#endif
223/* Define to 1 if needed for POSIX-compatible behavior. */
224#ifndef _POSIX_SOURCE
225# undef _POSIX_SOURCE
226#endif
227/* Define to 2 if needed for POSIX-compatible behavior. */
228#ifndef _POSIX_1_SOURCE
229# undef _POSIX_1_SOURCE
230#endif
231/* Enable POSIX-compatible threading on Solaris. */
232#ifndef _POSIX_PTHREAD_SEMANTICS
233# undef _POSIX_PTHREAD_SEMANTICS
234#endif
235/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
236#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
237# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
238#endif
239/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
240#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
241# undef __STDC_WANT_IEC_60559_BFP_EXT__
242#endif
243/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
244#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
245# undef __STDC_WANT_IEC_60559_DFP_EXT__
246#endif
247/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
248#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
249# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
250#endif
251/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
252#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
253# undef __STDC_WANT_IEC_60559_TYPES_EXT__
254#endif
255/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
256#ifndef __STDC_WANT_LIB_EXT2__
257# undef __STDC_WANT_LIB_EXT2__
258#endif
259/* Enable extensions specified by ISO/IEC 24747:2009. */
260#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
261# undef __STDC_WANT_MATH_SPEC_FUNCS__
262#endif
263/* Enable extensions on HP NonStop. */
264#ifndef _TANDEM_SOURCE
265# undef _TANDEM_SOURCE
266#endif
267/* Enable X/Open extensions. Define to 500 only if necessary
268 to make mbstate_t available. */
269#ifndef _XOPEN_SOURCE
270# undef _XOPEN_SOURCE
271#endif
272
273
274/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
275 significant byte first (like Motorola and SPARC, unlike Intel). */
276#if defined AC_APPLE_UNIVERSAL_BUILD
277# if defined __BIG_ENDIAN__
278# define WORDS_BIGENDIAN 1
279# endif
280#else
281# ifndef WORDS_BIGENDIAN
282# undef WORDS_BIGENDIAN
283# endif
284#endif
285
286/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
287 <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
288 #define below would cause a syntax error. */
289#undef _UINT32_T
290
291/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
292 <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
293 #define below would cause a syntax error. */
294#undef _UINT64_T
295
296/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
297 <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
298 #define below would cause a syntax error. */
299#undef _UINT8_T
300
301/* Define as a signed integer type capable of holding a process identifier. */
302#undef pid_t
303
304/* Define to `unsigned int' if <sys/types.h> does not define. */
305#undef size_t
306
307/* Define to `int' if <sys/types.h> does not define. */
308#undef ssize_t
309
310/* Define to the type of an unsigned integer type of width exactly 16 bits if
311 such a type exists and the standard includes do not define it. */
312#undef uint16_t
313
314/* Define to the type of an unsigned integer type of width exactly 32 bits if
315 such a type exists and the standard includes do not define it. */
316#undef uint32_t
317
318/* Define to the type of an unsigned integer type of width exactly 64 bits if
319 such a type exists and the standard includes do not define it. */
320#undef uint64_t
321
322/* Define to the type of an unsigned integer type of width exactly 8 bits if
323 such a type exists and the standard includes do not define it. */
324#undef uint8_t
325
326/* Define to the type of an unsigned integer type wide enough to hold a
327 pointer, if such a type exists, and if the system does not define it. */
328#undef uintptr_t
329
330
331#ifdef HAVE_STDBOOL_H
332# include <stdbool.h>
333#else
334# ifndef HAVE__BOOL
335# ifdef __cplusplus
336typedef bool _Bool;
337# else
338# define _Bool signed char
339# endif
340# endif
341# define bool _Bool
342# define false 0
343# define true 1
344# define __bool_true_false_are_defined 1
345#endif
346
347#ifdef HAVE_SYS_PARAM_H
348#include <sys/param.h>
349#endif /* HAVE_SYS_PARAM_H */
350
351#ifndef MAX
352#define MAX(a, b) ((a) > (b) ? (a) : (b))
353#endif /* MAX */
354
355#ifndef MIN
356#define MIN(a, b) ((a) < (b) ? (a) : (b))
357#endif /* MIN */
358
diff --git a/exec/config.sub b/exec/config.sub
new file mode 100755
index 00000000000..b41da55df45
--- /dev/null
+++ b/exec/config.sub
@@ -0,0 +1,1890 @@
1#!/usr/bin/sh
2# Configuration validation subroutine script.
3# Copyright 1992-2022 Free Software Foundation, Inc.
4
5# shellcheck disable=SC2006,SC2268 # see below for rationale
6
7timestamp='2022-01-03'
8
9# This file is free software; you can redistribute it and/or modify it
10# under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful, but
15# WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17# General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, see <https://www.gnu.org/licenses/>.
21#
22# As a special exception to the GNU General Public License, if you
23# distribute this file as part of a program that contains a
24# configuration script generated by Autoconf, you may include it under
25# the same distribution terms that you use for the rest of that
26# program. This Exception is an additional permission under section 7
27# of the GNU General Public License, version 3 ("GPLv3").
28
29
30# Please send patches to <config-patches@gnu.org>.
31#
32# Configuration subroutine to validate and canonicalize a configuration type.
33# Supply the specified configuration type as an argument.
34# If it is invalid, we print an error message on stderr and exit with code 1.
35# Otherwise, we print the canonical config type on stdout and succeed.
36
37# You can get the latest version of this script from:
38# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
39
40# This file is supposed to be the same for all GNU packages
41# and recognize all the CPU types, system types and aliases
42# that are meaningful with *any* GNU software.
43# Each package is responsible for reporting which valid configurations
44# it does not support. The user should be able to distinguish
45# a failure to support a valid configuration from a meaningless
46# configuration.
47
48# The goal of this file is to map all the various variations of a given
49# machine specification into a single specification in the form:
50# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
51# or in some cases, the newer four-part form:
52# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
53# It is wrong to echo any other type of specification.
54
55# The "shellcheck disable" line above the timestamp inhibits complaints
56# about features and limitations of the classic Bourne shell that were
57# superseded or lifted in POSIX. However, this script identifies a wide
58# variety of pre-POSIX systems that do not have POSIX shells at all, and
59# even some reasonably current systems (Solaris 10 as case-in-point) still
60# have a pre-POSIX /bin/sh.
61
62me=`echo "$0" | sed -e 's,.*/,,'`
63
64usage="\
65Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
66
67Canonicalize a configuration name.
68
69Options:
70 -h, --help print this help, then exit
71 -t, --time-stamp print date of last modification, then exit
72 -v, --version print version number, then exit
73
74Report bugs and patches to <config-patches@gnu.org>."
75
76version="\
77GNU config.sub ($timestamp)
78
79Copyright 1992-2022 Free Software Foundation, Inc.
80
81This is free software; see the source for copying conditions. There is NO
82warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
83
84help="
85Try \`$me --help' for more information."
86
87# Parse command line
88while test $# -gt 0 ; do
89 case $1 in
90 --time-stamp | --time* | -t )
91 echo "$timestamp" ; exit ;;
92 --version | -v )
93 echo "$version" ; exit ;;
94 --help | --h* | -h )
95 echo "$usage"; exit ;;
96 -- ) # Stop option processing
97 shift; break ;;
98 - ) # Use stdin as input.
99 break ;;
100 -* )
101 echo "$me: invalid option $1$help" >&2
102 exit 1 ;;
103
104 *local*)
105 # First pass through any local machine types.
106 echo "$1"
107 exit ;;
108
109 * )
110 break ;;
111 esac
112done
113
114case $# in
115 0) echo "$me: missing argument$help" >&2
116 exit 1;;
117 1) ;;
118 *) echo "$me: too many arguments$help" >&2
119 exit 1;;
120esac
121
122# Split fields of configuration type
123# shellcheck disable=SC2162
124saved_IFS=$IFS
125IFS="-" read field1 field2 field3 field4 <<EOF
126$1
127EOF
128IFS=$saved_IFS
129
130# Separate into logical components for further validation
131case $1 in
132 *-*-*-*-*)
133 echo Invalid configuration \`"$1"\': more than four components >&2
134 exit 1
135 ;;
136 *-*-*-*)
137 basic_machine=$field1-$field2
138 basic_os=$field3-$field4
139 ;;
140 *-*-*)
141 # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
142 # parts
143 maybe_os=$field2-$field3
144 case $maybe_os in
145 nto-qnx* | linux-* | uclinux-uclibc* \
146 | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
147 | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
148 | storm-chaos* | os2-emx* | rtmk-nova*)
149 basic_machine=$field1
150 basic_os=$maybe_os
151 ;;
152 android-linux)
153 basic_machine=$field1-unknown
154 basic_os=linux-android
155 ;;
156 *)
157 basic_machine=$field1-$field2
158 basic_os=$field3
159 ;;
160 esac
161 ;;
162 *-*)
163 # A lone config we happen to match not fitting any pattern
164 case $field1-$field2 in
165 decstation-3100)
166 basic_machine=mips-dec
167 basic_os=
168 ;;
169 *-*)
170 # Second component is usually, but not always the OS
171 case $field2 in
172 # Prevent following clause from handling this valid os
173 sun*os*)
174 basic_machine=$field1
175 basic_os=$field2
176 ;;
177 zephyr*)
178 basic_machine=$field1-unknown
179 basic_os=$field2
180 ;;
181 # Manufacturers
182 dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
183 | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
184 | unicom* | ibm* | next | hp | isi* | apollo | altos* \
185 | convergent* | ncr* | news | 32* | 3600* | 3100* \
186 | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \
187 | ultra | tti* | harris | dolphin | highlevel | gould \
188 | cbm | ns | masscomp | apple | axis | knuth | cray \
189 | microblaze* | sim | cisco \
190 | oki | wec | wrs | winbond)
191 basic_machine=$field1-$field2
192 basic_os=
193 ;;
194 *)
195 basic_machine=$field1
196 basic_os=$field2
197 ;;
198 esac
199 ;;
200 esac
201 ;;
202 *)
203 # Convert single-component short-hands not valid as part of
204 # multi-component configurations.
205 case $field1 in
206 386bsd)
207 basic_machine=i386-pc
208 basic_os=bsd
209 ;;
210 a29khif)
211 basic_machine=a29k-amd
212 basic_os=udi
213 ;;
214 adobe68k)
215 basic_machine=m68010-adobe
216 basic_os=scout
217 ;;
218 alliant)
219 basic_machine=fx80-alliant
220 basic_os=
221 ;;
222 altos | altos3068)
223 basic_machine=m68k-altos
224 basic_os=
225 ;;
226 am29k)
227 basic_machine=a29k-none
228 basic_os=bsd
229 ;;
230 amdahl)
231 basic_machine=580-amdahl
232 basic_os=sysv
233 ;;
234 amiga)
235 basic_machine=m68k-unknown
236 basic_os=
237 ;;
238 amigaos | amigados)
239 basic_machine=m68k-unknown
240 basic_os=amigaos
241 ;;
242 amigaunix | amix)
243 basic_machine=m68k-unknown
244 basic_os=sysv4
245 ;;
246 apollo68)
247 basic_machine=m68k-apollo
248 basic_os=sysv
249 ;;
250 apollo68bsd)
251 basic_machine=m68k-apollo
252 basic_os=bsd
253 ;;
254 aros)
255 basic_machine=i386-pc
256 basic_os=aros
257 ;;
258 aux)
259 basic_machine=m68k-apple
260 basic_os=aux
261 ;;
262 balance)
263 basic_machine=ns32k-sequent
264 basic_os=dynix
265 ;;
266 blackfin)
267 basic_machine=bfin-unknown
268 basic_os=linux
269 ;;
270 cegcc)
271 basic_machine=arm-unknown
272 basic_os=cegcc
273 ;;
274 convex-c1)
275 basic_machine=c1-convex
276 basic_os=bsd
277 ;;
278 convex-c2)
279 basic_machine=c2-convex
280 basic_os=bsd
281 ;;
282 convex-c32)
283 basic_machine=c32-convex
284 basic_os=bsd
285 ;;
286 convex-c34)
287 basic_machine=c34-convex
288 basic_os=bsd
289 ;;
290 convex-c38)
291 basic_machine=c38-convex
292 basic_os=bsd
293 ;;
294 cray)
295 basic_machine=j90-cray
296 basic_os=unicos
297 ;;
298 crds | unos)
299 basic_machine=m68k-crds
300 basic_os=
301 ;;
302 da30)
303 basic_machine=m68k-da30
304 basic_os=
305 ;;
306 decstation | pmax | pmin | dec3100 | decstatn)
307 basic_machine=mips-dec
308 basic_os=
309 ;;
310 delta88)
311 basic_machine=m88k-motorola
312 basic_os=sysv3
313 ;;
314 dicos)
315 basic_machine=i686-pc
316 basic_os=dicos
317 ;;
318 djgpp)
319 basic_machine=i586-pc
320 basic_os=msdosdjgpp
321 ;;
322 ebmon29k)
323 basic_machine=a29k-amd
324 basic_os=ebmon
325 ;;
326 es1800 | OSE68k | ose68k | ose | OSE)
327 basic_machine=m68k-ericsson
328 basic_os=ose
329 ;;
330 gmicro)
331 basic_machine=tron-gmicro
332 basic_os=sysv
333 ;;
334 go32)
335 basic_machine=i386-pc
336 basic_os=go32
337 ;;
338 h8300hms)
339 basic_machine=h8300-hitachi
340 basic_os=hms
341 ;;
342 h8300xray)
343 basic_machine=h8300-hitachi
344 basic_os=xray
345 ;;
346 h8500hms)
347 basic_machine=h8500-hitachi
348 basic_os=hms
349 ;;
350 harris)
351 basic_machine=m88k-harris
352 basic_os=sysv3
353 ;;
354 hp300 | hp300hpux)
355 basic_machine=m68k-hp
356 basic_os=hpux
357 ;;
358 hp300bsd)
359 basic_machine=m68k-hp
360 basic_os=bsd
361 ;;
362 hppaosf)
363 basic_machine=hppa1.1-hp
364 basic_os=osf
365 ;;
366 hppro)
367 basic_machine=hppa1.1-hp
368 basic_os=proelf
369 ;;
370 i386mach)
371 basic_machine=i386-mach
372 basic_os=mach
373 ;;
374 isi68 | isi)
375 basic_machine=m68k-isi
376 basic_os=sysv
377 ;;
378 m68knommu)
379 basic_machine=m68k-unknown
380 basic_os=linux
381 ;;
382 magnum | m3230)
383 basic_machine=mips-mips
384 basic_os=sysv
385 ;;
386 merlin)
387 basic_machine=ns32k-utek
388 basic_os=sysv
389 ;;
390 mingw64)
391 basic_machine=x86_64-pc
392 basic_os=mingw64
393 ;;
394 mingw32)
395 basic_machine=i686-pc
396 basic_os=mingw32
397 ;;
398 mingw32ce)
399 basic_machine=arm-unknown
400 basic_os=mingw32ce
401 ;;
402 monitor)
403 basic_machine=m68k-rom68k
404 basic_os=coff
405 ;;
406 morphos)
407 basic_machine=powerpc-unknown
408 basic_os=morphos
409 ;;
410 moxiebox)
411 basic_machine=moxie-unknown
412 basic_os=moxiebox
413 ;;
414 msdos)
415 basic_machine=i386-pc
416 basic_os=msdos
417 ;;
418 msys)
419 basic_machine=i686-pc
420 basic_os=msys
421 ;;
422 mvs)
423 basic_machine=i370-ibm
424 basic_os=mvs
425 ;;
426 nacl)
427 basic_machine=le32-unknown
428 basic_os=nacl
429 ;;
430 ncr3000)
431 basic_machine=i486-ncr
432 basic_os=sysv4
433 ;;
434 netbsd386)
435 basic_machine=i386-pc
436 basic_os=netbsd
437 ;;
438 netwinder)
439 basic_machine=armv4l-rebel
440 basic_os=linux
441 ;;
442 news | news700 | news800 | news900)
443 basic_machine=m68k-sony
444 basic_os=newsos
445 ;;
446 news1000)
447 basic_machine=m68030-sony
448 basic_os=newsos
449 ;;
450 necv70)
451 basic_machine=v70-nec
452 basic_os=sysv
453 ;;
454 nh3000)
455 basic_machine=m68k-harris
456 basic_os=cxux
457 ;;
458 nh[45]000)
459 basic_machine=m88k-harris
460 basic_os=cxux
461 ;;
462 nindy960)
463 basic_machine=i960-intel
464 basic_os=nindy
465 ;;
466 mon960)
467 basic_machine=i960-intel
468 basic_os=mon960
469 ;;
470 nonstopux)
471 basic_machine=mips-compaq
472 basic_os=nonstopux
473 ;;
474 os400)
475 basic_machine=powerpc-ibm
476 basic_os=os400
477 ;;
478 OSE68000 | ose68000)
479 basic_machine=m68000-ericsson
480 basic_os=ose
481 ;;
482 os68k)
483 basic_machine=m68k-none
484 basic_os=os68k
485 ;;
486 paragon)
487 basic_machine=i860-intel
488 basic_os=osf
489 ;;
490 parisc)
491 basic_machine=hppa-unknown
492 basic_os=linux
493 ;;
494 psp)
495 basic_machine=mipsallegrexel-sony
496 basic_os=psp
497 ;;
498 pw32)
499 basic_machine=i586-unknown
500 basic_os=pw32
501 ;;
502 rdos | rdos64)
503 basic_machine=x86_64-pc
504 basic_os=rdos
505 ;;
506 rdos32)
507 basic_machine=i386-pc
508 basic_os=rdos
509 ;;
510 rom68k)
511 basic_machine=m68k-rom68k
512 basic_os=coff
513 ;;
514 sa29200)
515 basic_machine=a29k-amd
516 basic_os=udi
517 ;;
518 sei)
519 basic_machine=mips-sei
520 basic_os=seiux
521 ;;
522 sequent)
523 basic_machine=i386-sequent
524 basic_os=
525 ;;
526 sps7)
527 basic_machine=m68k-bull
528 basic_os=sysv2
529 ;;
530 st2000)
531 basic_machine=m68k-tandem
532 basic_os=
533 ;;
534 stratus)
535 basic_machine=i860-stratus
536 basic_os=sysv4
537 ;;
538 sun2)
539 basic_machine=m68000-sun
540 basic_os=
541 ;;
542 sun2os3)
543 basic_machine=m68000-sun
544 basic_os=sunos3
545 ;;
546 sun2os4)
547 basic_machine=m68000-sun
548 basic_os=sunos4
549 ;;
550 sun3)
551 basic_machine=m68k-sun
552 basic_os=
553 ;;
554 sun3os3)
555 basic_machine=m68k-sun
556 basic_os=sunos3
557 ;;
558 sun3os4)
559 basic_machine=m68k-sun
560 basic_os=sunos4
561 ;;
562 sun4)
563 basic_machine=sparc-sun
564 basic_os=
565 ;;
566 sun4os3)
567 basic_machine=sparc-sun
568 basic_os=sunos3
569 ;;
570 sun4os4)
571 basic_machine=sparc-sun
572 basic_os=sunos4
573 ;;
574 sun4sol2)
575 basic_machine=sparc-sun
576 basic_os=solaris2
577 ;;
578 sun386 | sun386i | roadrunner)
579 basic_machine=i386-sun
580 basic_os=
581 ;;
582 sv1)
583 basic_machine=sv1-cray
584 basic_os=unicos
585 ;;
586 symmetry)
587 basic_machine=i386-sequent
588 basic_os=dynix
589 ;;
590 t3e)
591 basic_machine=alphaev5-cray
592 basic_os=unicos
593 ;;
594 t90)
595 basic_machine=t90-cray
596 basic_os=unicos
597 ;;
598 toad1)
599 basic_machine=pdp10-xkl
600 basic_os=tops20
601 ;;
602 tpf)
603 basic_machine=s390x-ibm
604 basic_os=tpf
605 ;;
606 udi29k)
607 basic_machine=a29k-amd
608 basic_os=udi
609 ;;
610 ultra3)
611 basic_machine=a29k-nyu
612 basic_os=sym1
613 ;;
614 v810 | necv810)
615 basic_machine=v810-nec
616 basic_os=none
617 ;;
618 vaxv)
619 basic_machine=vax-dec
620 basic_os=sysv
621 ;;
622 vms)
623 basic_machine=vax-dec
624 basic_os=vms
625 ;;
626 vsta)
627 basic_machine=i386-pc
628 basic_os=vsta
629 ;;
630 vxworks960)
631 basic_machine=i960-wrs
632 basic_os=vxworks
633 ;;
634 vxworks68)
635 basic_machine=m68k-wrs
636 basic_os=vxworks
637 ;;
638 vxworks29k)
639 basic_machine=a29k-wrs
640 basic_os=vxworks
641 ;;
642 xbox)
643 basic_machine=i686-pc
644 basic_os=mingw32
645 ;;
646 ymp)
647 basic_machine=ymp-cray
648 basic_os=unicos
649 ;;
650 *)
651 basic_machine=$1
652 basic_os=
653 ;;
654 esac
655 ;;
656esac
657
658# Decode 1-component or ad-hoc basic machines
659case $basic_machine in
660 # Here we handle the default manufacturer of certain CPU types. It is in
661 # some cases the only manufacturer, in others, it is the most popular.
662 w89k)
663 cpu=hppa1.1
664 vendor=winbond
665 ;;
666 op50n)
667 cpu=hppa1.1
668 vendor=oki
669 ;;
670 op60c)
671 cpu=hppa1.1
672 vendor=oki
673 ;;
674 ibm*)
675 cpu=i370
676 vendor=ibm
677 ;;
678 orion105)
679 cpu=clipper
680 vendor=highlevel
681 ;;
682 mac | mpw | mac-mpw)
683 cpu=m68k
684 vendor=apple
685 ;;
686 pmac | pmac-mpw)
687 cpu=powerpc
688 vendor=apple
689 ;;
690
691 # Recognize the various machine names and aliases which stand
692 # for a CPU type and a company and sometimes even an OS.
693 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
694 cpu=m68000
695 vendor=att
696 ;;
697 3b*)
698 cpu=we32k
699 vendor=att
700 ;;
701 bluegene*)
702 cpu=powerpc
703 vendor=ibm
704 basic_os=cnk
705 ;;
706 decsystem10* | dec10*)
707 cpu=pdp10
708 vendor=dec
709 basic_os=tops10
710 ;;
711 decsystem20* | dec20*)
712 cpu=pdp10
713 vendor=dec
714 basic_os=tops20
715 ;;
716 delta | 3300 | motorola-3300 | motorola-delta \
717 | 3300-motorola | delta-motorola)
718 cpu=m68k
719 vendor=motorola
720 ;;
721 dpx2*)
722 cpu=m68k
723 vendor=bull
724 basic_os=sysv3
725 ;;
726 encore | umax | mmax)
727 cpu=ns32k
728 vendor=encore
729 ;;
730 elxsi)
731 cpu=elxsi
732 vendor=elxsi
733 basic_os=${basic_os:-bsd}
734 ;;
735 fx2800)
736 cpu=i860
737 vendor=alliant
738 ;;
739 genix)
740 cpu=ns32k
741 vendor=ns
742 ;;
743 h3050r* | hiux*)
744 cpu=hppa1.1
745 vendor=hitachi
746 basic_os=hiuxwe2
747 ;;
748 hp3k9[0-9][0-9] | hp9[0-9][0-9])
749 cpu=hppa1.0
750 vendor=hp
751 ;;
752 hp9k2[0-9][0-9] | hp9k31[0-9])
753 cpu=m68000
754 vendor=hp
755 ;;
756 hp9k3[2-9][0-9])
757 cpu=m68k
758 vendor=hp
759 ;;
760 hp9k6[0-9][0-9] | hp6[0-9][0-9])
761 cpu=hppa1.0
762 vendor=hp
763 ;;
764 hp9k7[0-79][0-9] | hp7[0-79][0-9])
765 cpu=hppa1.1
766 vendor=hp
767 ;;
768 hp9k78[0-9] | hp78[0-9])
769 # FIXME: really hppa2.0-hp
770 cpu=hppa1.1
771 vendor=hp
772 ;;
773 hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
774 # FIXME: really hppa2.0-hp
775 cpu=hppa1.1
776 vendor=hp
777 ;;
778 hp9k8[0-9][13679] | hp8[0-9][13679])
779 cpu=hppa1.1
780 vendor=hp
781 ;;
782 hp9k8[0-9][0-9] | hp8[0-9][0-9])
783 cpu=hppa1.0
784 vendor=hp
785 ;;
786 i*86v32)
787 cpu=`echo "$1" | sed -e 's/86.*/86/'`
788 vendor=pc
789 basic_os=sysv32
790 ;;
791 i*86v4*)
792 cpu=`echo "$1" | sed -e 's/86.*/86/'`
793 vendor=pc
794 basic_os=sysv4
795 ;;
796 i*86v)
797 cpu=`echo "$1" | sed -e 's/86.*/86/'`
798 vendor=pc
799 basic_os=sysv
800 ;;
801 i*86sol2)
802 cpu=`echo "$1" | sed -e 's/86.*/86/'`
803 vendor=pc
804 basic_os=solaris2
805 ;;
806 j90 | j90-cray)
807 cpu=j90
808 vendor=cray
809 basic_os=${basic_os:-unicos}
810 ;;
811 iris | iris4d)
812 cpu=mips
813 vendor=sgi
814 case $basic_os in
815 irix*)
816 ;;
817 *)
818 basic_os=irix4
819 ;;
820 esac
821 ;;
822 miniframe)
823 cpu=m68000
824 vendor=convergent
825 ;;
826 *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
827 cpu=m68k
828 vendor=atari
829 basic_os=mint
830 ;;
831 news-3600 | risc-news)
832 cpu=mips
833 vendor=sony
834 basic_os=newsos
835 ;;
836 next | m*-next)
837 cpu=m68k
838 vendor=next
839 case $basic_os in
840 openstep*)
841 ;;
842 nextstep*)
843 ;;
844 ns2*)
845 basic_os=nextstep2
846 ;;
847 *)
848 basic_os=nextstep3
849 ;;
850 esac
851 ;;
852 np1)
853 cpu=np1
854 vendor=gould
855 ;;
856 op50n-* | op60c-*)
857 cpu=hppa1.1
858 vendor=oki
859 basic_os=proelf
860 ;;
861 pa-hitachi)
862 cpu=hppa1.1
863 vendor=hitachi
864 basic_os=hiuxwe2
865 ;;
866 pbd)
867 cpu=sparc
868 vendor=tti
869 ;;
870 pbb)
871 cpu=m68k
872 vendor=tti
873 ;;
874 pc532)
875 cpu=ns32k
876 vendor=pc532
877 ;;
878 pn)
879 cpu=pn
880 vendor=gould
881 ;;
882 power)
883 cpu=power
884 vendor=ibm
885 ;;
886 ps2)
887 cpu=i386
888 vendor=ibm
889 ;;
890 rm[46]00)
891 cpu=mips
892 vendor=siemens
893 ;;
894 rtpc | rtpc-*)
895 cpu=romp
896 vendor=ibm
897 ;;
898 sde)
899 cpu=mipsisa32
900 vendor=sde
901 basic_os=${basic_os:-elf}
902 ;;
903 simso-wrs)
904 cpu=sparclite
905 vendor=wrs
906 basic_os=vxworks
907 ;;
908 tower | tower-32)
909 cpu=m68k
910 vendor=ncr
911 ;;
912 vpp*|vx|vx-*)
913 cpu=f301
914 vendor=fujitsu
915 ;;
916 w65)
917 cpu=w65
918 vendor=wdc
919 ;;
920 w89k-*)
921 cpu=hppa1.1
922 vendor=winbond
923 basic_os=proelf
924 ;;
925 none)
926 cpu=none
927 vendor=none
928 ;;
929 leon|leon[3-9])
930 cpu=sparc
931 vendor=$basic_machine
932 ;;
933 leon-*|leon[3-9]-*)
934 cpu=sparc
935 vendor=`echo "$basic_machine" | sed 's/-.*//'`
936 ;;
937
938 *-*)
939 # shellcheck disable=SC2162
940 saved_IFS=$IFS
941 IFS="-" read cpu vendor <<EOF
942$basic_machine
943EOF
944 IFS=$saved_IFS
945 ;;
946 # We use `pc' rather than `unknown'
947 # because (1) that's what they normally are, and
948 # (2) the word "unknown" tends to confuse beginning users.
949 i*86 | x86_64)
950 cpu=$basic_machine
951 vendor=pc
952 ;;
953 # These rules are duplicated from below for sake of the special case above;
954 # i.e. things that normalized to x86 arches should also default to "pc"
955 pc98)
956 cpu=i386
957 vendor=pc
958 ;;
959 x64 | amd64)
960 cpu=x86_64
961 vendor=pc
962 ;;
963 # Recognize the basic CPU types without company name.
964 *)
965 cpu=$basic_machine
966 vendor=unknown
967 ;;
968esac
969
970unset -v basic_machine
971
972# Decode basic machines in the full and proper CPU-Company form.
973case $cpu-$vendor in
974 # Here we handle the default manufacturer of certain CPU types in canonical form. It is in
975 # some cases the only manufacturer, in others, it is the most popular.
976 craynv-unknown)
977 vendor=cray
978 basic_os=${basic_os:-unicosmp}
979 ;;
980 c90-unknown | c90-cray)
981 vendor=cray
982 basic_os=${Basic_os:-unicos}
983 ;;
984 fx80-unknown)
985 vendor=alliant
986 ;;
987 romp-unknown)
988 vendor=ibm
989 ;;
990 mmix-unknown)
991 vendor=knuth
992 ;;
993 microblaze-unknown | microblazeel-unknown)
994 vendor=xilinx
995 ;;
996 rs6000-unknown)
997 vendor=ibm
998 ;;
999 vax-unknown)
1000 vendor=dec
1001 ;;
1002 pdp11-unknown)
1003 vendor=dec
1004 ;;
1005 we32k-unknown)
1006 vendor=att
1007 ;;
1008 cydra-unknown)
1009 vendor=cydrome
1010 ;;
1011 i370-ibm*)
1012 vendor=ibm
1013 ;;
1014 orion-unknown)
1015 vendor=highlevel
1016 ;;
1017 xps-unknown | xps100-unknown)
1018 cpu=xps100
1019 vendor=honeywell
1020 ;;
1021
1022 # Here we normalize CPU types with a missing or matching vendor
1023 armh-unknown | armh-alt)
1024 cpu=armv7l
1025 vendor=alt
1026 basic_os=${basic_os:-linux-gnueabihf}
1027 ;;
1028 dpx20-unknown | dpx20-bull)
1029 cpu=rs6000
1030 vendor=bull
1031 basic_os=${basic_os:-bosx}
1032 ;;
1033
1034 # Here we normalize CPU types irrespective of the vendor
1035 amd64-*)
1036 cpu=x86_64
1037 ;;
1038 blackfin-*)
1039 cpu=bfin
1040 basic_os=linux
1041 ;;
1042 c54x-*)
1043 cpu=tic54x
1044 ;;
1045 c55x-*)
1046 cpu=tic55x
1047 ;;
1048 c6x-*)
1049 cpu=tic6x
1050 ;;
1051 e500v[12]-*)
1052 cpu=powerpc
1053 basic_os=${basic_os}"spe"
1054 ;;
1055 mips3*-*)
1056 cpu=mips64
1057 ;;
1058 ms1-*)
1059 cpu=mt
1060 ;;
1061 m68knommu-*)
1062 cpu=m68k
1063 basic_os=linux
1064 ;;
1065 m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
1066 cpu=s12z
1067 ;;
1068 openrisc-*)
1069 cpu=or32
1070 ;;
1071 parisc-*)
1072 cpu=hppa
1073 basic_os=linux
1074 ;;
1075 pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
1076 cpu=i586
1077 ;;
1078 pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
1079 cpu=i686
1080 ;;
1081 pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
1082 cpu=i686
1083 ;;
1084 pentium4-*)
1085 cpu=i786
1086 ;;
1087 pc98-*)
1088 cpu=i386
1089 ;;
1090 ppc-* | ppcbe-*)
1091 cpu=powerpc
1092 ;;
1093 ppcle-* | powerpclittle-*)
1094 cpu=powerpcle
1095 ;;
1096 ppc64-*)
1097 cpu=powerpc64
1098 ;;
1099 ppc64le-* | powerpc64little-*)
1100 cpu=powerpc64le
1101 ;;
1102 sb1-*)
1103 cpu=mipsisa64sb1
1104 ;;
1105 sb1el-*)
1106 cpu=mipsisa64sb1el
1107 ;;
1108 sh5e[lb]-*)
1109 cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'`
1110 ;;
1111 spur-*)
1112 cpu=spur
1113 ;;
1114 strongarm-* | thumb-*)
1115 cpu=arm
1116 ;;
1117 tx39-*)
1118 cpu=mipstx39
1119 ;;
1120 tx39el-*)
1121 cpu=mipstx39el
1122 ;;
1123 x64-*)
1124 cpu=x86_64
1125 ;;
1126 xscale-* | xscalee[bl]-*)
1127 cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
1128 ;;
1129 arm64-* | aarch64le-*)
1130 cpu=aarch64
1131 ;;
1132
1133 # Recognize the canonical CPU Types that limit and/or modify the
1134 # company names they are paired with.
1135 cr16-*)
1136 basic_os=${basic_os:-elf}
1137 ;;
1138 crisv32-* | etraxfs*-*)
1139 cpu=crisv32
1140 vendor=axis
1141 ;;
1142 cris-* | etrax*-*)
1143 cpu=cris
1144 vendor=axis
1145 ;;
1146 crx-*)
1147 basic_os=${basic_os:-elf}
1148 ;;
1149 neo-tandem)
1150 cpu=neo
1151 vendor=tandem
1152 ;;
1153 nse-tandem)
1154 cpu=nse
1155 vendor=tandem
1156 ;;
1157 nsr-tandem)
1158 cpu=nsr
1159 vendor=tandem
1160 ;;
1161 nsv-tandem)
1162 cpu=nsv
1163 vendor=tandem
1164 ;;
1165 nsx-tandem)
1166 cpu=nsx
1167 vendor=tandem
1168 ;;
1169 mipsallegrexel-sony)
1170 cpu=mipsallegrexel
1171 vendor=sony
1172 ;;
1173 tile*-*)
1174 basic_os=${basic_os:-linux-gnu}
1175 ;;
1176
1177 *)
1178 # Recognize the canonical CPU types that are allowed with any
1179 # company name.
1180 case $cpu in
1181 1750a | 580 \
1182 | a29k \
1183 | aarch64 | aarch64_be \
1184 | abacus \
1185 | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
1186 | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
1187 | alphapca5[67] | alpha64pca5[67] \
1188 | am33_2.0 \
1189 | amdgcn \
1190 | arc | arceb | arc32 | arc64 \
1191 | arm | arm[lb]e | arme[lb] | armv* \
1192 | avr | avr32 \
1193 | asmjs \
1194 | ba \
1195 | be32 | be64 \
1196 | bfin | bpf | bs2000 \
1197 | c[123]* | c30 | [cjt]90 | c4x \
1198 | c8051 | clipper | craynv | csky | cydra \
1199 | d10v | d30v | dlx | dsp16xx \
1200 | e2k | elxsi | epiphany \
1201 | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
1202 | h8300 | h8500 \
1203 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
1204 | hexagon \
1205 | i370 | i*86 | i860 | i960 | ia16 | ia64 \
1206 | ip2k | iq2000 \
1207 | k1om \
1208 | le32 | le64 \
1209 | lm32 \
1210 | loongarch32 | loongarch64 | loongarchx32 \
1211 | m32c | m32r | m32rle \
1212 | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
1213 | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
1214 | m88110 | m88k | maxq | mb | mcore | mep | metag \
1215 | microblaze | microblazeel \
1216 | mips | mipsbe | mipseb | mipsel | mipsle \
1217 | mips16 \
1218 | mips64 | mips64eb | mips64el \
1219 | mips64octeon | mips64octeonel \
1220 | mips64orion | mips64orionel \
1221 | mips64r5900 | mips64r5900el \
1222 | mips64vr | mips64vrel \
1223 | mips64vr4100 | mips64vr4100el \
1224 | mips64vr4300 | mips64vr4300el \
1225 | mips64vr5000 | mips64vr5000el \
1226 | mips64vr5900 | mips64vr5900el \
1227 | mipsisa32 | mipsisa32el \
1228 | mipsisa32r2 | mipsisa32r2el \
1229 | mipsisa32r3 | mipsisa32r3el \
1230 | mipsisa32r5 | mipsisa32r5el \
1231 | mipsisa32r6 | mipsisa32r6el \
1232 | mipsisa64 | mipsisa64el \
1233 | mipsisa64r2 | mipsisa64r2el \
1234 | mipsisa64r3 | mipsisa64r3el \
1235 | mipsisa64r5 | mipsisa64r5el \
1236 | mipsisa64r6 | mipsisa64r6el \
1237 | mipsisa64sb1 | mipsisa64sb1el \
1238 | mipsisa64sr71k | mipsisa64sr71kel \
1239 | mipsr5900 | mipsr5900el \
1240 | mipstx39 | mipstx39el \
1241 | mmix \
1242 | mn10200 | mn10300 \
1243 | moxie \
1244 | mt \
1245 | msp430 \
1246 | nds32 | nds32le | nds32be \
1247 | nfp \
1248 | nios | nios2 | nios2eb | nios2el \
1249 | none | np1 | ns16k | ns32k | nvptx \
1250 | open8 \
1251 | or1k* \
1252 | or32 \
1253 | orion \
1254 | picochip \
1255 | pdp10 | pdp11 | pj | pjl | pn | power \
1256 | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
1257 | pru \
1258 | pyramid \
1259 | riscv | riscv32 | riscv32be | riscv64 | riscv64be \
1260 | rl78 | romp | rs6000 | rx \
1261 | s390 | s390x \
1262 | score \
1263 | sh | shl \
1264 | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
1265 | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
1266 | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
1267 | sparclite \
1268 | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
1269 | spu \
1270 | tahoe \
1271 | thumbv7* \
1272 | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
1273 | tron \
1274 | ubicom32 \
1275 | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
1276 | vax \
1277 | visium \
1278 | w65 \
1279 | wasm32 | wasm64 \
1280 | we32k \
1281 | x86 | x86_64 | xc16x | xgate | xps100 \
1282 | xstormy16 | xtensa* \
1283 | ymp \
1284 | z8k | z80)
1285 ;;
1286
1287 *)
1288 echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
1289 exit 1
1290 ;;
1291 esac
1292 ;;
1293esac
1294
1295# Here we canonicalize certain aliases for manufacturers.
1296case $vendor in
1297 digital*)
1298 vendor=dec
1299 ;;
1300 commodore*)
1301 vendor=cbm
1302 ;;
1303 *)
1304 ;;
1305esac
1306
1307# Decode manufacturer-specific aliases for certain operating systems.
1308
1309if test x$basic_os != x
1310then
1311
1312# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
1313# set os.
1314case $basic_os in
1315 gnu/linux*)
1316 kernel=linux
1317 os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'`
1318 ;;
1319 os2-emx)
1320 kernel=os2
1321 os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'`
1322 ;;
1323 nto-qnx*)
1324 kernel=nto
1325 os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'`
1326 ;;
1327 *-*)
1328 # shellcheck disable=SC2162
1329 saved_IFS=$IFS
1330 IFS="-" read kernel os <<EOF
1331$basic_os
1332EOF
1333 IFS=$saved_IFS
1334 ;;
1335 # Default OS when just kernel was specified
1336 nto*)
1337 kernel=nto
1338 os=`echo "$basic_os" | sed -e 's|nto|qnx|'`
1339 ;;
1340 linux*)
1341 kernel=linux
1342 os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
1343 ;;
1344 *)
1345 kernel=
1346 os=$basic_os
1347 ;;
1348esac
1349
1350# Now, normalize the OS (knowing we just have one component, it's not a kernel,
1351# etc.)
1352case $os in
1353 # First match some system type aliases that might get confused
1354 # with valid system types.
1355 # solaris* is a basic system type, with this one exception.
1356 auroraux)
1357 os=auroraux
1358 ;;
1359 bluegene*)
1360 os=cnk
1361 ;;
1362 solaris1 | solaris1.*)
1363 os=`echo "$os" | sed -e 's|solaris1|sunos4|'`
1364 ;;
1365 solaris)
1366 os=solaris2
1367 ;;
1368 unixware*)
1369 os=sysv4.2uw
1370 ;;
1371 # es1800 is here to avoid being matched by es* (a different OS)
1372 es1800*)
1373 os=ose
1374 ;;
1375 # Some version numbers need modification
1376 chorusos*)
1377 os=chorusos
1378 ;;
1379 isc)
1380 os=isc2.2
1381 ;;
1382 sco6)
1383 os=sco5v6
1384 ;;
1385 sco5)
1386 os=sco3.2v5
1387 ;;
1388 sco4)
1389 os=sco3.2v4
1390 ;;
1391 sco3.2.[4-9]*)
1392 os=`echo "$os" | sed -e 's/sco3.2./sco3.2v/'`
1393 ;;
1394 sco*v* | scout)
1395 # Don't match below
1396 ;;
1397 sco*)
1398 os=sco3.2v2
1399 ;;
1400 psos*)
1401 os=psos
1402 ;;
1403 qnx*)
1404 os=qnx
1405 ;;
1406 hiux*)
1407 os=hiuxwe2
1408 ;;
1409 lynx*178)
1410 os=lynxos178
1411 ;;
1412 lynx*5)
1413 os=lynxos5
1414 ;;
1415 lynxos*)
1416 # don't get caught up in next wildcard
1417 ;;
1418 lynx*)
1419 os=lynxos
1420 ;;
1421 mac[0-9]*)
1422 os=`echo "$os" | sed -e 's|mac|macos|'`
1423 ;;
1424 opened*)
1425 os=openedition
1426 ;;
1427 os400*)
1428 os=os400
1429 ;;
1430 sunos5*)
1431 os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
1432 ;;
1433 sunos6*)
1434 os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
1435 ;;
1436 wince*)
1437 os=wince
1438 ;;
1439 utek*)
1440 os=bsd
1441 ;;
1442 dynix*)
1443 os=bsd
1444 ;;
1445 acis*)
1446 os=aos
1447 ;;
1448 atheos*)
1449 os=atheos
1450 ;;
1451 syllable*)
1452 os=syllable
1453 ;;
1454 386bsd)
1455 os=bsd
1456 ;;
1457 ctix* | uts*)
1458 os=sysv
1459 ;;
1460 nova*)
1461 os=rtmk-nova
1462 ;;
1463 ns2)
1464 os=nextstep2
1465 ;;
1466 # Preserve the version number of sinix5.
1467 sinix5.*)
1468 os=`echo "$os" | sed -e 's|sinix|sysv|'`
1469 ;;
1470 sinix*)
1471 os=sysv4
1472 ;;
1473 tpf*)
1474 os=tpf
1475 ;;
1476 triton*)
1477 os=sysv3
1478 ;;
1479 oss*)
1480 os=sysv3
1481 ;;
1482 svr4*)
1483 os=sysv4
1484 ;;
1485 svr3)
1486 os=sysv3
1487 ;;
1488 sysvr4)
1489 os=sysv4
1490 ;;
1491 ose*)
1492 os=ose
1493 ;;
1494 *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
1495 os=mint
1496 ;;
1497 dicos*)
1498 os=dicos
1499 ;;
1500 pikeos*)
1501 # Until real need of OS specific support for
1502 # particular features comes up, bare metal
1503 # configurations are quite functional.
1504 case $cpu in
1505 arm*)
1506 os=eabi
1507 ;;
1508 *)
1509 os=elf
1510 ;;
1511 esac
1512 ;;
1513 *)
1514 # No normalization, but not necessarily accepted, that comes below.
1515 ;;
1516esac
1517
1518else
1519
1520# Here we handle the default operating systems that come with various machines.
1521# The value should be what the vendor currently ships out the door with their
1522# machine or put another way, the most popular os provided with the machine.
1523
1524# Note that if you're going to try to match "-MANUFACTURER" here (say,
1525# "-sun"), then you have to tell the case statement up towards the top
1526# that MANUFACTURER isn't an operating system. Otherwise, code above
1527# will signal an error saying that MANUFACTURER isn't an operating
1528# system, and we'll never get to this point.
1529
1530kernel=
1531case $cpu-$vendor in
1532 score-*)
1533 os=elf
1534 ;;
1535 spu-*)
1536 os=elf
1537 ;;
1538 *-acorn)
1539 os=riscix1.2
1540 ;;
1541 arm*-rebel)
1542 kernel=linux
1543 os=gnu
1544 ;;
1545 arm*-semi)
1546 os=aout
1547 ;;
1548 c4x-* | tic4x-*)
1549 os=coff
1550 ;;
1551 c8051-*)
1552 os=elf
1553 ;;
1554 clipper-intergraph)
1555 os=clix
1556 ;;
1557 hexagon-*)
1558 os=elf
1559 ;;
1560 tic54x-*)
1561 os=coff
1562 ;;
1563 tic55x-*)
1564 os=coff
1565 ;;
1566 tic6x-*)
1567 os=coff
1568 ;;
1569 # This must come before the *-dec entry.
1570 pdp10-*)
1571 os=tops20
1572 ;;
1573 pdp11-*)
1574 os=none
1575 ;;
1576 *-dec | vax-*)
1577 os=ultrix4.2
1578 ;;
1579 m68*-apollo)
1580 os=domain
1581 ;;
1582 i386-sun)
1583 os=sunos4.0.2
1584 ;;
1585 m68000-sun)
1586 os=sunos3
1587 ;;
1588 m68*-cisco)
1589 os=aout
1590 ;;
1591 mep-*)
1592 os=elf
1593 ;;
1594 mips*-cisco)
1595 os=elf
1596 ;;
1597 mips*-*)
1598 os=elf
1599 ;;
1600 or32-*)
1601 os=coff
1602 ;;
1603 *-tti) # must be before sparc entry or we get the wrong os.
1604 os=sysv3
1605 ;;
1606 sparc-* | *-sun)
1607 os=sunos4.1.1
1608 ;;
1609 pru-*)
1610 os=elf
1611 ;;
1612 *-be)
1613 os=beos
1614 ;;
1615 *-ibm)
1616 os=aix
1617 ;;
1618 *-knuth)
1619 os=mmixware
1620 ;;
1621 *-wec)
1622 os=proelf
1623 ;;
1624 *-winbond)
1625 os=proelf
1626 ;;
1627 *-oki)
1628 os=proelf
1629 ;;
1630 *-hp)
1631 os=hpux
1632 ;;
1633 *-hitachi)
1634 os=hiux
1635 ;;
1636 i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
1637 os=sysv
1638 ;;
1639 *-cbm)
1640 os=amigaos
1641 ;;
1642 *-dg)
1643 os=dgux
1644 ;;
1645 *-dolphin)
1646 os=sysv3
1647 ;;
1648 m68k-ccur)
1649 os=rtu
1650 ;;
1651 m88k-omron*)
1652 os=luna
1653 ;;
1654 *-next)
1655 os=nextstep
1656 ;;
1657 *-sequent)
1658 os=ptx
1659 ;;
1660 *-crds)
1661 os=unos
1662 ;;
1663 *-ns)
1664 os=genix
1665 ;;
1666 i370-*)
1667 os=mvs
1668 ;;
1669 *-gould)
1670 os=sysv
1671 ;;
1672 *-highlevel)
1673 os=bsd
1674 ;;
1675 *-encore)
1676 os=bsd
1677 ;;
1678 *-sgi)
1679 os=irix
1680 ;;
1681 *-siemens)
1682 os=sysv4
1683 ;;
1684 *-masscomp)
1685 os=rtu
1686 ;;
1687 f30[01]-fujitsu | f700-fujitsu)
1688 os=uxpv
1689 ;;
1690 *-rom68k)
1691 os=coff
1692 ;;
1693 *-*bug)
1694 os=coff
1695 ;;
1696 *-apple)
1697 os=macos
1698 ;;
1699 *-atari*)
1700 os=mint
1701 ;;
1702 *-wrs)
1703 os=vxworks
1704 ;;
1705 *)
1706 os=none
1707 ;;
1708esac
1709
1710fi
1711
1712# Now, validate our (potentially fixed-up) OS.
1713case $os in
1714 # Sometimes we do "kernel-libc", so those need to count as OSes.
1715 musl* | newlib* | relibc* | uclibc*)
1716 ;;
1717 # Likewise for "kernel-abi"
1718 eabi* | gnueabi*)
1719 ;;
1720 # VxWorks passes extra cpu info in the 4th filed.
1721 simlinux | simwindows | spe)
1722 ;;
1723 # Now accept the basic system types.
1724 # The portable systems comes first.
1725 # Each alternative MUST end in a * to match a version number.
1726 gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
1727 | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \
1728 | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
1729 | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \
1730 | hiux* | abug | nacl* | netware* | windows* \
1731 | os9* | macos* | osx* | ios* \
1732 | mpw* | magic* | mmixware* | mon960* | lnews* \
1733 | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
1734 | aos* | aros* | cloudabi* | sortix* | twizzler* \
1735 | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
1736 | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
1737 | mirbsd* | netbsd* | dicos* | openedition* | ose* \
1738 | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
1739 | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
1740 | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
1741 | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
1742 | udi* | lites* | ieee* | go32* | aux* | hcos* \
1743 | chorusrdb* | cegcc* | glidix* | serenity* \
1744 | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
1745 | midipix* | mingw32* | mingw64* | mint* \
1746 | uxpv* | beos* | mpeix* | udk* | moxiebox* \
1747 | interix* | uwin* | mks* | rhapsody* | darwin* \
1748 | openstep* | oskit* | conix* | pw32* | nonstopux* \
1749 | storm-chaos* | tops10* | tenex* | tops20* | its* \
1750 | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \
1751 | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \
1752 | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
1753 | skyos* | haiku* | rdos* | toppers* | drops* | es* \
1754 | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
1755 | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
1756 | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
1757 | fiwix* )
1758 ;;
1759 # This one is extra strict with allowed versions
1760 sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
1761 # Don't forget version if it is 3.2v4 or newer.
1762 ;;
1763 none)
1764 ;;
1765 *)
1766 echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
1767 exit 1
1768 ;;
1769esac
1770
1771# As a final step for OS-related things, validate the OS-kernel combination
1772# (given a valid OS), if there is a kernel.
1773case $kernel-$os in
1774 linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
1775 | linux-musl* | linux-relibc* | linux-uclibc* )
1776 ;;
1777 uclinux-uclibc* )
1778 ;;
1779 -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* )
1780 # These are just libc implementations, not actual OSes, and thus
1781 # require a kernel.
1782 echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
1783 exit 1
1784 ;;
1785 kfreebsd*-gnu* | kopensolaris*-gnu*)
1786 ;;
1787 vxworks-simlinux | vxworks-simwindows | vxworks-spe)
1788 ;;
1789 nto-qnx*)
1790 ;;
1791 os2-emx)
1792 ;;
1793 *-eabi* | *-gnueabi*)
1794 ;;
1795 -*)
1796 # Blank kernel with real OS is always fine.
1797 ;;
1798 *-*)
1799 echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
1800 exit 1
1801 ;;
1802esac
1803
1804# Here we handle the case where we know the os, and the CPU type, but not the
1805# manufacturer. We pick the logical manufacturer.
1806case $vendor in
1807 unknown)
1808 case $cpu-$os in
1809 *-riscix*)
1810 vendor=acorn
1811 ;;
1812 *-sunos*)
1813 vendor=sun
1814 ;;
1815 *-cnk* | *-aix*)
1816 vendor=ibm
1817 ;;
1818 *-beos*)
1819 vendor=be
1820 ;;
1821 *-hpux*)
1822 vendor=hp
1823 ;;
1824 *-mpeix*)
1825 vendor=hp
1826 ;;
1827 *-hiux*)
1828 vendor=hitachi
1829 ;;
1830 *-unos*)
1831 vendor=crds
1832 ;;
1833 *-dgux*)
1834 vendor=dg
1835 ;;
1836 *-luna*)
1837 vendor=omron
1838 ;;
1839 *-genix*)
1840 vendor=ns
1841 ;;
1842 *-clix*)
1843 vendor=intergraph
1844 ;;
1845 *-mvs* | *-opened*)
1846 vendor=ibm
1847 ;;
1848 *-os400*)
1849 vendor=ibm
1850 ;;
1851 s390-* | s390x-*)
1852 vendor=ibm
1853 ;;
1854 *-ptx*)
1855 vendor=sequent
1856 ;;
1857 *-tpf*)
1858 vendor=ibm
1859 ;;
1860 *-vxsim* | *-vxworks* | *-windiss*)
1861 vendor=wrs
1862 ;;
1863 *-aux*)
1864 vendor=apple
1865 ;;
1866 *-hms*)
1867 vendor=hitachi
1868 ;;
1869 *-mpw* | *-macos*)
1870 vendor=apple
1871 ;;
1872 *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
1873 vendor=atari
1874 ;;
1875 *-vos*)
1876 vendor=stratus
1877 ;;
1878 esac
1879 ;;
1880esac
1881
1882echo "$cpu-$vendor-${kernel:+$kernel-}$os"
1883exit
1884
1885# Local variables:
1886# eval: (add-hook 'before-save-hook 'time-stamp)
1887# time-stamp-start: "timestamp='"
1888# time-stamp-format: "%:y-%02m-%02d"
1889# time-stamp-end: "'"
1890# End:
diff --git a/exec/configure.ac b/exec/configure.ac
new file mode 100644
index 00000000000..e78d8ebea90
--- /dev/null
+++ b/exec/configure.ac
@@ -0,0 +1,537 @@
1dnl Autoconf script for GNU Emacs's exec library.
2dnl To rebuild the 'configure' script from this, execute the command
3dnl autoconf
4dnl in the directory containing this script.
5dnl If you changed any AC_DEFINES, also run autoheader.
6dnl
7dnl Copyright (C) 2023 Free Software Foundation, Inc.
8dnl
9dnl This file is part of GNU Emacs.
10dnl
11dnl GNU Emacs is free software: you can redistribute it and/or modify
12dnl it under the terms of the GNU General Public License as published by
13dnl the Free Software Foundation, either version 3 of the License, or
14dnl (at your option) any later version.
15dnl
16dnl GNU Emacs is distributed in the hope that it will be useful,
17dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
18dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19dnl GNU General Public License for more details.
20dnl
21dnl You should have received a copy of the GNU General Public License
22dnl along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
23
24AC_PREREQ([2.65])
25AC_INIT([libexec], [30.0.50], [bug-gnu-emacs@gnu.org], [],
26 [https://www.gnu.org/software/emacs/])
27
28AH_TOP([/* Copyright (C) 2023 Free Software Foundation, Inc.
29
30This file is part of GNU Emacs.
31
32GNU Emacs is free software: you can redistribute it and/or modify it
33under the terms of the GNU General Public License as published by the
34Free Software Foundation, either version 3 of the License, or (at your
35option) any later version.
36
37GNU Emacs is distributed in the hope that it will be useful, but
38WITHOUT ANY WARRANTY; without even the implied warranty of
39MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
40General Public License for more details.
41
42You should have received a copy of the GNU General Public License
43along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */])
44
45AC_ARG_WITH([reentrancy],
46 [AS_HELP_STRING([--with-reentrancy],
47 [Generate library which can be used within a signal handler.])],
48 [AC_DEFINE([REENTRANT], [1])])
49
50AC_USE_SYSTEM_EXTENSIONS
51AC_PROG_CC
52AC_PROG_CPP
53AC_PROG_INSTALL
54
55AC_TYPE_UINT8_T
56AC_TYPE_UINT16_T
57AC_TYPE_UINT32_T
58AC_TYPE_UINT64_T
59AC_TYPE_UINTPTR_T
60AC_TYPE_SIZE_T
61AC_TYPE_SSIZE_T
62AC_TYPE_PID_T
63
64AC_HEADER_STDBOOL
65AC_CHECK_FUNCS([getpagesize stpcpy stpncpy])
66AC_CHECK_DECLS([stpcpy, stpncpy])
67AC_CHECK_FUNC([process_vm_readv],
68 [AC_CHECK_FUNC([process_vm_writev],
69 [AC_CHECK_DECL([process_vm_readv],
70 [AC_DEFINE([HAVE_PROCESS_VM], [1],
71 [Define to 1 if process_vm_readv is available.])],
72 [], [[
73#include <sys/uio.h>
74 ]])])])
75AC_CHECK_HEADERS([sys/param.h sys/uio.h])
76AC_CHECK_MEMBERS([siginfo_t.si_syscall], [], [],
77 [[
78#include <signal.h>
79 ]])
80
81AH_BOTTOM([
82#ifdef HAVE_STDBOOL_H
83# include <stdbool.h>
84#else
85# ifndef HAVE__BOOL
86# ifdef __cplusplus
87typedef bool _Bool;
88# else
89# define _Bool signed char
90# endif
91# endif
92# define bool _Bool
93# define false 0
94# define true 1
95# define __bool_true_false_are_defined 1
96#endif
97
98#ifdef HAVE_SYS_PARAM_H
99#include <sys/param.h>
100#endif /* HAVE_SYS_PARAM_H */
101
102#ifndef MAX
103#define MAX(a, b) ((a) > (b) ? (a) : (b))
104#endif /* MAX */
105
106#ifndef MIN
107#define MIN(a, b) ((a) < (b) ? (a) : (b))
108#endif /* MIN */
109])
110
111AC_C_BIGENDIAN
112
113AH_TEMPLATE([SYSCALL_HEADER], [Define to header holding system call numbers.])
114AH_TEMPLATE([USER_HEADER], [Define to header holding USER_REGS_STRUCT.])
115AH_TEMPLATE([USER_REGS_STRUCT], [Define to structure holding user registers.])
116AH_TEMPLATE([SYSCALL_NUM_REG], [Define to register holding the system call number.])
117AH_TEMPLATE([SYSCALL_ARG_REG], [Define to register holding arg0 to system calls.])
118AH_TEMPLATE([SYSCALL_ARG1_REG], [Define to register holding arg1 to system calls.])
119AH_TEMPLATE([SYSCALL_ARG2_REG], [Define to register holding arg2 to system calls.])
120AH_TEMPLATE([SYSCALL_ARG3_REG], [Define to register holding arg3 to system calls.])
121AH_TEMPLATE([SYSCALL_RET_REG], [Define to register holding value of system calls.])
122AH_TEMPLATE([STACK_POINTER], [Define to register holding the stack pointer.])
123AH_TEMPLATE([EXEC_SYSCALL], [Define to number of the `exec' system call.])
124AH_TEMPLATE([USER_WORD], [Define to word type used by tracees.])
125AH_TEMPLATE([EXEC_64], [Define to 1 if the system utilizes 64-bit ELF.])
126AH_TEMPLATE([STACK_GROWS_DOWNWARDS], [Define to 1 if the stack grows downwards.])
127AH_TEMPLATE([ABI_RED_ZONE], [Define to number of reserved bytes past the stack frame.])
128AH_TEMPLATE([EXECUTABLE_BASE], [Virtual address for loading PIC executables])
129AH_TEMPLATE([INTERPRETER_BASE], [Virtual address for loading PIC interpreters])
130AH_TEMPLATE([CLONE_SYSCALL], [Define to number of the `clone' system call.])
131AH_TEMPLATE([CLONE3_SYSCALL], [Define to number of the `clone3' system call.])
132AH_TEMPLATE([READLINK_SYSCALL], [Define to number of the `readlink' system call.])
133AH_TEMPLATE([READLINKAT_SYSCALL], [Define to number of the `readlinkat' system call.])
134AH_TEMPLATE([REENTRANT], [Define to 1 if the library is used within a signal handler.])
135
136AC_CANONICAL_HOST
137
138# Check whether or not sys/user exists. If it doesn't, try
139# asm/user.h, and croak if that doesn't exist either.
140AS_CASE([$host], [*mips*], [], [*],
141 [AC_CHECK_HEADER([sys/user.h], [user_h="<sys/user.h>"],
142 [AC_CHECK_HEADER([asm/user.h], [user_h="<asm/user.h>"],
143 [AC_MSG_ERROR([Can not find working user.h])])])])
144
145# Look for required tools.
146
147AC_ARG_VAR([M4], [`m4' preprocessor command.])
148AC_ARG_VAR([AS], [`as' assembler command.])
149AC_ARG_VAR([LD], [`ld' linker command.])
150
151# Check for a working m4.
152AC_CHECK_PROGS([M4], [gm4 m4],
153 [AC_MSG_ERROR([Cannot find m4])])
154
155# Check for a working assembler.
156AC_CHECK_TOOL([AS], [as],
157 [AC_MSG_ERROR([Cannot find a working assembler])])
158
159# And ar.
160AC_CHECK_TOOL([AR], [ar],
161 [AC_MSG_ERROR([Cannot find a working ar])])
162
163# And ld.
164AC_CHECK_TOOL([LD], [ld],
165 [AC_MSG_ERROR([Cannot find a working linker])])
166
167# Now check if ld is a C compiler.
168LDPREFIX=
169AC_CACHE_CHECK([whether ld is a C compiler],
170 [exec_cv_ld_is_cc],
171 [cat <<_ACEOF > conftest.c
172AC_LANG_PROGRAM(,)
173_ACEOF
174 exec_cv_ld_is_cc=yes
175 $LD -c conftest.c -o conftest.$OBJEXT >&AS_MESSAGE_LOG_FD 2>&1 \
176 || exec_cv_ld_is_cc=no
177 rm -f conftest.c conftest.$OBJEXT])
178
179# And if as is a C compiler.
180AC_CACHE_CHECK([whether as is a C compiler],
181 [exec_cv_as_is_cc],
182 [cat <<_ACEOF > conftest.c
183AC_LANG_PROGRAM(,)
184_ACEOF
185 exec_cv_as_is_cc=yes
186 $AS -c conftest.c -o conftest.$OBJEXT >&AS_MESSAGE_LOG_FD 2>&1 \
187 || exec_cv_as_is_cc=no
188 rm -f conftest.c conftest.$OBJEXT])
189
190# If ld is a C compiler, pass `-nostdlib', `-nostartfiles', and
191# `-static'. Also, set LDPREFIX to -Wl,
192AS_IF([test "x$exec_cv_ld_is_cc" = "xyes"],
193 [LOADERFLAGS="$LOADERFLAGS -nostdlib -nostartfiles -static"
194 LDPREFIX=-Wl,])
195
196# If as is a C compiler, add `-c' to ASFLAGS.
197AS_IF([test "x$exec_cv_as_is_cc" = "xyes"],
198 [ASFLAGS="$ASFLAGS -c"])
199
200AC_DEFUN([exec_CHECK_LINUX_CLONE3],
201[
202AC_CHECK_DECL([__NR_clone3],
203 [AC_DEFINE([CLONE3_SYSCALL], [__NR_clone3])],
204 [], [[
205#include <asm/unistd.h>
206]])
207])
208
209AC_DEFUN([exec_CHECK_MIPS_NABI],
210[
211AC_CACHE_CHECK([whether MIPS NABI calling convention is used],
212 [exec_cv_mips_nabi],
213 [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
214#include <sgidefs.h>
215]], [[
216#ifndef __mips64__
217#if _MIPS_SIM == _ABIO32
218OABI in use.
219#endif /* _MIPS_SIM == _ABIO32 */
220#endif /* !__mips64__ */
221]])], [exec_cv_mips_nabi=yes],
222 [exec_cv_mips_nabi=no])])
223
224dnl mips64 systems use N64 calling convention, a variant of nabi
225dnl calling convention.
226AS_IF([test "x$exec_cv_mips_nabi" != "xno"],
227 [AC_DEFINE([MIPS_NABI], [1],
228 [Define to 1 if MIPS NABI calling convention is being used.])],
229 [OBJS="$OBJS mipsfpu.o"])
230])
231
232# Determine the system type and define appropriate macros.
233exec_loader=
234is_mips=
235OBJS="exec.o trace.o"
236DADDI_BROKEN=no
237
238AS_CASE([$host], [x86_64-*linux*],
239 [AC_CHECK_MEMBER([struct user_regs_struct.rdi],
240 [AC_DEFINE([SYSCALL_HEADER], [<asm/unistd.h>])
241 AC_DEFINE_UNQUOTED([USER_HEADER], [$user_h])
242 AC_DEFINE([USER_REGS_STRUCT], [struct user_regs_struct])
243 AC_DEFINE([SYSCALL_NUM_REG], [orig_rax])
244 AC_DEFINE([SYSCALL_RET_REG], [rax])
245 AC_DEFINE([SYSCALL_ARG_REG], [rdi])
246 AC_DEFINE([SYSCALL_ARG1_REG], [rsi])
247 AC_DEFINE([SYSCALL_ARG2_REG], [rdx])
248 AC_DEFINE([SYSCALL_ARG3_REG], [r10])
249 AC_DEFINE([STACK_POINTER], [rsp])
250 AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
251 AC_DEFINE([USER_WORD], [uintptr_t])
252 AC_DEFINE([EXEC_64], [1])
253 AC_DEFINE([ABI_RED_ZONE], [128])
254 AC_DEFINE([EXECUTABLE_BASE], [0x555555554000])
255 AC_DEFINE([INTERPRETER_BASE], [0x600000000000])
256 AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
257 AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
258 AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
259 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
260 exec_CHECK_LINUX_CLONE3
261 # Make sure the loader doesn't conflict with other position
262 # dependent code.
263 LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x200000000000"
264 exec_loader=loader-x86_64.s],
265 [AC_MSG_ERROR([Missing `rdi' in user_regs_struct])],
266 [[
267#include $user_h
268 ]])], [i[[34567]]86-*linux*],
269 [AC_CHECK_MEMBER([struct user_regs_struct.edi],
270 [AC_DEFINE([SYSCALL_HEADER], [<asm/unistd.h>])
271 AC_DEFINE_UNQUOTED([USER_HEADER], [$user_h])
272 AC_DEFINE([USER_REGS_STRUCT], [struct user_regs_struct])
273 AC_DEFINE([SYSCALL_NUM_REG], [orig_eax])
274 AC_DEFINE([SYSCALL_RET_REG], [eax])
275 AC_DEFINE([SYSCALL_ARG_REG], [ebx])
276 AC_DEFINE([SYSCALL_ARG1_REG], [ecx])
277 AC_DEFINE([SYSCALL_ARG2_REG], [edx])
278 AC_DEFINE([SYSCALL_ARG3_REG], [esi])
279 AC_DEFINE([STACK_POINTER], [esp])
280 AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
281 AC_DEFINE([USER_WORD], [uintptr_t])
282 AC_DEFINE([EXECUTABLE_BASE], [0x0f000000])
283 AC_DEFINE([INTERPRETER_BASE], [0xaf000000])
284 AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
285 AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
286 AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
287 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
288 exec_CHECK_LINUX_CLONE3
289 # Make sure the loader doesn't conflict with other position
290 # dependent code.
291 LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0xa0000000"
292 exec_loader=loader-x86.s],
293 [AC_MSG_ERROR([Missing `edi' in user_regs_struct])],
294 [[
295#include $user_h
296 ]])], [aarch64-*linux*],
297 [AC_CHECK_MEMBER([struct user_regs_struct.sp],
298 [AC_DEFINE([SYSCALL_HEADER], [<asm/unistd.h>])
299 AC_DEFINE_UNQUOTED([USER_HEADER], [$user_h])
300 AC_DEFINE([USER_REGS_STRUCT], [struct user_regs_struct])
301 AC_DEFINE([SYSCALL_NUM_REG], [[regs[8]]])
302 AC_DEFINE([SYSCALL_RET_REG], [[regs[0]]])
303 AC_DEFINE([SYSCALL_ARG_REG], [[regs[0]]])
304 AC_DEFINE([SYSCALL_ARG1_REG], [[regs[1]]])
305 AC_DEFINE([SYSCALL_ARG2_REG], [[regs[2]]])
306 AC_DEFINE([SYSCALL_ARG3_REG], [[regs[3]]])
307 AC_DEFINE([STACK_POINTER], [sp])
308 AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
309 AC_DEFINE([USER_WORD], [uintptr_t])
310 AC_DEFINE([EXEC_64], [1])
311 AC_DEFINE([EXECUTABLE_BASE], [0x3000000000])
312 AC_DEFINE([INTERPRETER_BASE], [0x3f00000000])
313 AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
314 AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
315 # Note that aarch64 has no `readlink'.
316 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
317 exec_CHECK_LINUX_CLONE3
318 # Make sure the loader doesn't conflict with other position
319 # dependent code. ARM places rather significant restrictions on
320 # virtual addresses for a 64 bit architecture.
321 LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x2000000000"
322 exec_loader=loader-aarch64.s],
323 [AC_MSG_ERROR([Missing `sp' in user_regs_struct])],
324 [[
325#include $user_h
326 ]])], [arm*linux*eabi* | armv7*linux*],
327 [AC_CHECK_MEMBER([struct user_regs.uregs],
328 [AC_DEFINE([SYSCALL_HEADER], [<asm/unistd.h>])
329 AC_DEFINE_UNQUOTED([USER_HEADER], [$user_h])
330 AC_DEFINE([USER_REGS_STRUCT], [struct user_regs])
331 AC_DEFINE([SYSCALL_NUM_REG], [[uregs[7]]])
332 AC_DEFINE([SYSCALL_RET_REG], [[uregs[0]]])
333 AC_DEFINE([SYSCALL_ARG_REG], [[uregs[0]]])
334 AC_DEFINE([SYSCALL_ARG1_REG], [[uregs[1]]])
335 AC_DEFINE([SYSCALL_ARG2_REG], [[uregs[2]]])
336 AC_DEFINE([SYSCALL_ARG3_REG], [[uregs[3]]])
337 AC_DEFINE([STACK_POINTER], [[uregs[13]]])
338 AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
339 AC_DEFINE([USER_WORD], [uintptr_t])
340 AC_DEFINE([EXECUTABLE_BASE], [0x0f000000])
341 AC_DEFINE([INTERPRETER_BASE], [0x1f000000])
342 AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
343 AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
344 AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
345 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
346 exec_CHECK_LINUX_CLONE3
347 LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000"
348 exec_loader=loader-armeabi.s],
349 [AC_CHECK_MEMBER([struct pt_regs.uregs],
350 [AC_DEFINE([SYSCALL_HEADER], [<asm/unistd.h>])
351 AC_DEFINE_UNQUOTED([USER_HEADER], [<asm/ptrace.h>])
352 AC_DEFINE([USER_REGS_STRUCT], [struct pt_regs])
353 AC_DEFINE([SYSCALL_NUM_REG], [[uregs[7]]])
354 AC_DEFINE([SYSCALL_RET_REG], [[uregs[0]]])
355 AC_DEFINE([SYSCALL_ARG_REG], [[uregs[0]]])
356 AC_DEFINE([SYSCALL_ARG1_REG], [[uregs[1]]])
357 AC_DEFINE([SYSCALL_ARG2_REG], [[uregs[2]]])
358 AC_DEFINE([SYSCALL_ARG3_REG], [[uregs[3]]])
359 AC_DEFINE([STACK_POINTER], [[uregs[13]]])
360 AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
361 AC_DEFINE([USER_WORD], [uintptr_t])
362 AC_DEFINE([EXECUTABLE_BASE], [0x0f000000])
363 AC_DEFINE([INTERPRETER_BASE], [0x1f000000])
364 AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
365 AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
366 AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
367 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
368 exec_CHECK_LINUX_CLONE3
369 LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000"
370 exec_loader=loader-armeabi.s],
371 [AC_MSG_ERROR([Missing `uregs' in user_regs_struct or pt_regs])],
372 [[
373#include <asm/ptrace.h>
374 ]])],
375 [[
376#include $user_h
377 ]])], [mipsel*linux*],
378 [AC_DEFINE([SYSCALL_HEADER], [<asm/unistd.h>])
379 AC_DEFINE([USER_HEADER], ["mipsel-user.h"])
380 AC_DEFINE([USER_REGS_STRUCT], [struct mipsel_regs])
381 AC_DEFINE([SYSCALL_NUM_REG], [[gregs[2]]]) # v0
382 AC_DEFINE([SYSCALL_RET_REG], [[gregs[4]]]) # a0
383 AC_DEFINE([SYSCALL_ARG_REG], [[gregs[4]]]) # a0
384 AC_DEFINE([SYSCALL_ARG1_REG], [[gregs[5]]]) # a1
385 AC_DEFINE([SYSCALL_ARG2_REG], [[gregs[4]]]) # a2
386 AC_DEFINE([SYSCALL_ARG3_REG], [[gregs[5]]]) # a3
387 AC_DEFINE([STACK_POINTER], [[gregs[29]]]) # sp
388 AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
389 AC_DEFINE([USER_WORD], [uintptr_t])
390 AC_DEFINE([EXECUTABLE_BASE], [0x0f000000])
391 AC_DEFINE([INTERPRETER_BASE], [0x1f000000])
392 AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
393 AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
394 AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
395 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
396 AC_CHECK_DECL([_MIPS_SIM], [exec_CHECK_MIPS_NABI],
397 [AC_MSG_ERROR([_MIPS_SIM could not be determined]),
398 [[
399#include <sgidefs.h>
400]]])
401 exec_CHECK_LINUX_CLONE3
402 LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000"
403 is_mips=yes
404 exec_loader=loader-mipsel.s], [mips64el*linux*],
405 [AC_DEFINE([SYSCALL_HEADER], [<asm/unistd.h>])
406 AC_DEFINE([USER_HEADER], ["mipsel-user.h"])
407 AC_DEFINE([USER_REGS_STRUCT], [struct mipsel_regs])
408 AC_DEFINE([SYSCALL_NUM_REG], [[gregs[2]]]) # v0
409 AC_DEFINE([SYSCALL_RET_REG], [[gregs[4]]]) # a0
410 AC_DEFINE([SYSCALL_ARG_REG], [[gregs[4]]]) # a0
411 AC_DEFINE([SYSCALL_ARG1_REG], [[gregs[5]]]) # a1
412 AC_DEFINE([SYSCALL_ARG2_REG], [[gregs[4]]]) # a2
413 AC_DEFINE([SYSCALL_ARG3_REG], [[gregs[5]]]) # a3
414 AC_DEFINE([STACK_POINTER], [[gregs[29]]]) # sp
415 AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
416 AC_DEFINE([USER_WORD], [uintptr_t])
417 AC_DEFINE([EXEC_64], [1])
418 AC_DEFINE([EXECUTABLE_BASE], [0x400000])
419 AC_DEFINE([INTERPRETER_BASE], [0x3f00000000])
420 AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
421 AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
422 AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
423 AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
424 AC_CACHE_CHECK([whether as understands `daddi'],
425 [exec_cv_as_daddi],
426 [exec_cv_as_daddi=no
427 cat <<_ACEOF >conftest.s
428 .section text
429 .global __start
430__start:
431 li $t0, 0
432 li $t1, 0
433 daddi $t0, $t1, 1
434 daddi $t0, $t1, -1
435 daddi $t0, -1
436 daddi $t0, 1
437
438_ACEOF
439 $AS $ASFLAGS conftest.s -o conftest.$OBJEXT \
440 >&AS_MESSAGE_LOG_FD 2>&1 \
441 && exec_cv_as_daddi=yes
442 rm -f conftest.s conftest.$OBJEXT])
443 AS_IF([test "x$exec_cv_as_daddi" != "xyes"],
444 [DADDI_BROKEN=yes])
445 exec_CHECK_LINUX_CLONE3
446 exec_CHECK_MIPS_NABI
447 LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x3e00000000"
448 is_mips=yes
449 exec_loader=loader-mips64el.s], [*],
450 [AC_MSG_ERROR([Please port libexec to $host])])
451
452AC_SUBST([DADDI_BROKEN])
453
454MIPS_N32=$exec_cv_mips_nabi
455
456AC_ARG_VAR([LOADERFLAGS], [Flags used to link the loader.])
457AC_ARG_VAR([ARFLAGS], [Flags for the archiver.])
458AC_ARG_VAR([ASFLAGS], [Flags for the assembler.])
459
460# Make the assembler optimize for code size. Don't do this on MIPS,
461# as the assembler code manages branch delays manually.
462
463AC_CACHE_CHECK([whether as understands -O],
464 [exec_cv_as_O],
465 [exec_cv_as_O=no
466 cat <<_ACEOF >conftest.s
467 .section text
468 .global _start
469_start:
470
471_ACEOF
472 $AS $ASFLAGS -O conftest.s -o conftest.$OBJEXT \
473 >&AS_MESSAGE_LOG_FD 2>&1 \
474 && exec_cv_as_O=yes
475 rm -f conftest.s conftest.$OBJEXT])
476
477AS_IF([test "$exec_cv_as_O" = "yes" \
478 && test "$is_mips" != "yes"],
479 [ASFLAGS="$ASFLAGS -O"])
480
481# Make the assembler generate debug information.
482
483AC_CACHE_CHECK([whether as understands -g],
484 [exec_cv_as_g],
485 [exec_cv_as_g=no
486 cat <<_ACEOF >conftest.s
487 .section text
488 .global _start
489_start:
490
491_ACEOF
492 $AS $ASFLAGS -g conftest.s -o conftest.$OBJEXT \
493 >&AS_MESSAGE_LOG_FD 2>&1 \
494 && exec_cv_as_g=yes
495 rm -f conftest.s conftest.$OBJEXT])
496AS_IF([test "$exec_cv_as_g" = "yes"], [ASFLAGS="$ASFLAGS -g"])
497
498# Check for the ability to automatically generate dependencies for C
499# source files.
500AUTO_DEPEND=no
501AS_IF([test "x$GCC" = xyes],
502 [AC_CACHE_CHECK([whether gcc understands -MMD -MF],
503 [exec_cv_autodepend],
504 [SAVE_CFLAGS="$CFLAGS"
505 CFLAGS="$CFLAGS -MMD -MF deps.d -MP"
506 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
507 [exec_cv_autodepend=yes],
508 [exec_cv_autodepend=no])
509 CFLAGS="$SAVE_CFLAGS"
510 test -f deps.d || emacs_cv_autodepend=no
511 rm -rf deps.d])
512 AS_IF([test "x$exec_cv_autodepend" = xyes],
513 [AUTO_DEPEND=yes
514 AS_MKDIR_P([deps])])])
515
516# Now check for some other stuff.
517
518AC_CACHE_CHECK([for 'find' args to delete a file],
519 [exec_cv_find_delete],
520 [AS_IF([touch conftest.tmp && find conftest.tmp -delete 2>/dev/null &&
521 test ! -f conftest.tmp], [exec_cv_find_delete="-delete"],
522 [exec_cv_find_delete="-exec rm -f {} ';'"])])
523FIND_DELETE=$exec_cv_find_delete
524AC_SUBST([FIND_DELETE])
525
526AC_CONFIG_HEADERS([config.h])
527AC_CONFIG_FILES([Makefile config-mips.m4])
528
529AC_SUBST([AUTO_DEPEND])
530AC_SUBST([LOADERFLAGS])
531AC_SUBST([ARFLAGS])
532AC_SUBST([ASFLAGS])
533AC_SUBST([exec_loader])
534AC_SUBST([MIPS_N32])
535AC_SUBST([OBJS])
536
537AC_OUTPUT
diff --git a/exec/deps.mk b/exec/deps.mk
new file mode 100644
index 00000000000..20fcd2dbc5a
--- /dev/null
+++ b/exec/deps.mk
@@ -0,0 +1,21 @@
1### deps.mk
2
3## Copyright (C) 2023 Free Software Foundation, Inc.
4
5## This file is part of GNU Emacs.
6
7## GNU Emacs is free software: you can redistribute it and/or modify
8## it under the terms of the GNU General Public License as published by
9## the Free Software Foundation, either version 3 of the License, or
10## (at your option) any later version.
11##
12## GNU Emacs is distributed in the hope that it will be useful,
13## but WITHOUT ANY WARRANTY; without even the implied warranty of
14## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15## GNU General Public License for more details.
16##
17## You should have received a copy of the GNU General Public License
18## along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20exec.o: exec.h config.h
21trace.o: exec.h config.h
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}
diff --git a/exec/exec.h b/exec/exec.h
new file mode 100644
index 00000000000..8ee74d7ca8b
--- /dev/null
+++ b/exec/exec.h
@@ -0,0 +1,201 @@
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
21
22#ifndef _EXEC_H_
23#define _EXEC_H_
24
25#ifdef HAVE_STDINT_H
26#include <stdint.h>
27#endif /* HAVE_STDINT_H */
28
29#include <sys/types.h>
30
31#include USER_HEADER
32
33/* Define a replacement for `uint64_t' if it's not present in the C
34 library. */
35
36#ifndef UINT64_MAX
37
38typedef struct
39{
40 uint32_t word1;
41 uint32_t word2;
42} xint64_t;
43
44#else /* UINT64_MAX */
45typedef uint64_t xint64_t;
46#endif /* !UINT64_MAX */
47
48
49
50/* 32-bit ELF headers. */
51
52struct elf_header_32
53{
54 unsigned char e_ident[16];
55 uint16_t e_type;
56 uint16_t e_machine;
57 uint32_t e_version;
58 uint32_t e_entry;
59 uint32_t e_phoff;
60 uint32_t e_shoff;
61 uint32_t e_flags;
62 uint16_t e_ehsize;
63 uint16_t e_phentsize;
64 uint16_t e_phnum;
65 uint16_t e_shentsize;
66 uint16_t e_shnum;
67 uint16_t e_shstrndx;
68};
69
70struct program_header_32
71{
72 uint32_t p_type;
73 uint32_t p_offset;
74 uint32_t p_vaddr;
75 uint32_t p_paddr;
76 uint32_t p_filesz;
77 uint32_t p_memsz;
78 uint32_t p_flags;
79 uint32_t p_align;
80};
81
82struct dt_entry_32
83{
84 uint32_t d_tag;
85 uint32_t d_val;
86};
87
88
89
90struct elf_header_64
91{
92 unsigned char e_ident[16];
93 uint16_t e_type;
94 uint16_t e_machine;
95 uint32_t e_version;
96 xint64_t e_entry;
97 xint64_t e_phoff;
98 xint64_t e_shoff;
99 uint32_t e_flags;
100 uint16_t e_ehsize;
101 uint16_t e_phentsize;
102 uint16_t e_phnum;
103 uint16_t e_shentsize;
104 uint16_t e_shnum;
105 uint16_t e_shstrndx;
106};
107
108struct program_header_64
109{
110 uint32_t p_type;
111 uint32_t p_flags;
112 xint64_t p_offset;
113 xint64_t p_vaddr;
114 xint64_t p_paddr;
115 xint64_t p_filesz;
116 xint64_t p_memsz;
117 xint64_t p_align;
118};
119
120struct dt_entry_64
121{
122 xint64_t d_tag;
123 xint64_t d_val;
124};
125
126
127
128/* Define some types to the correct values. */
129
130#ifdef EXEC_64
131typedef struct elf_header_64 elf_header;
132typedef struct program_header_64 program_header;
133typedef struct dt_entry_64 dt_entry;
134#else /* !EXEC_64 */
135typedef struct elf_header_32 elf_header;
136typedef struct program_header_32 program_header;
137typedef struct dt_entry_32 dt_entry;
138#endif /* EXEC_64 */
139
140
141
142/* Defined in trace.c. */
143
144/* Structure describing a process being traced. */
145
146struct exec_tracee
147{
148 /* The next process being traced. */
149 struct exec_tracee *next;
150
151 /* The thread ID of this process. */
152 pid_t pid;
153
154 /* Whether or not the tracee is currently waiting for a system call
155 to complete. */
156 bool waiting_for_syscall : 1;
157
158 /* Whether or not the tracee has been created but is not yet
159 processed by `handle_clone'. */
160 bool new_child : 1;
161
162#ifndef REENTRANT
163 /* Name of the executable being run. */
164 char *exec_file;
165#endif /* !REENTRANT */
166};
167
168
169
170#ifdef __aarch64__
171
172extern int aarch64_get_regs (pid_t, USER_REGS_STRUCT *);
173extern int aarch64_set_regs (pid_t, USER_REGS_STRUCT *, bool);
174
175#endif /* __aarch64__ */
176
177
178
179extern USER_WORD user_alloca (struct exec_tracee *, USER_REGS_STRUCT *,
180 USER_REGS_STRUCT *, USER_WORD);
181extern int user_copy (struct exec_tracee *, const unsigned char *,
182 USER_WORD, USER_WORD);
183extern void exec_init (const char *);
184
185
186
187extern int tracing_execve (const char *, char *const *,
188 char *const *);
189extern int after_fork (pid_t);
190extern pid_t exec_waitpid (pid_t, int *, int);
191
192
193
194/* Defined in exec.c. */
195
196extern char *exec_0 (char *, struct exec_tracee *,
197 size_t *, USER_REGS_STRUCT *);
198
199
200
201#endif /* _EXEC_H_ */
diff --git a/exec/exec1.c b/exec/exec1.c
new file mode 100644
index 00000000000..d77ca8adf54
--- /dev/null
+++ b/exec/exec1.c
@@ -0,0 +1,94 @@
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#include <unistd.h>
22#include <stdlib.h>
23#include <stdio.h>
24#include <sys/wait.h>
25
26#include "exec.h"
27
28/* exec1 is a program which takes another program and its arguments,
29 forks, and executes that program, all while tracing it and its
30 children to use the program execution mechanism defined in exec.c.
31
32 This is necessary to bypass security restrictions which prohibit
33 Emacs from loading executables from certain directories, by, in
34 effect, replacing the executable loader in the Linux kernel. */
35
36
37
38int
39main (int argc, char **argv)
40{
41 pid_t pid, pid1;
42 extern char **environ;
43 int wstatus;
44
45 pid1 = getpid ();
46 pid = fork ();
47
48 if (!pid)
49 {
50 /* Set the process group used to the parent. */
51 if (setpgid (0, pid1))
52 perror ("setpgid");
53
54 tracing_execve (argv[2], argv + 2, environ);
55
56 /* An error occured. Exit with failure. */
57 exit (127);
58 }
59 else
60 {
61 /* Provide the file name of the loader. */
62 exec_init (argv[1]);
63
64 if (after_fork (pid))
65 exit (127);
66
67 /* Start waiting for the process to exit. */
68
69 while (true)
70 {
71 pid1 = exec_waitpid (-1, &wstatus, 0);
72
73 /* If the child process exits normally, exit with its status
74 code. If not, raise the signal that caused it to
75 exit. */
76
77 if (pid == pid1)
78 {
79 if (WIFEXITED (wstatus))
80 exit (WEXITSTATUS (wstatus));
81 else /* if WIFSIGNALED (wstatus) */
82 {
83 raise (WTERMSIG (wstatus));
84
85 /* Just in case the signal raised doesn't cause an
86 exit. */
87 exit (127);
88 }
89 }
90
91 /* Otherwise, continue looping. */
92 }
93 }
94}
diff --git a/exec/install-sh b/exec/install-sh
new file mode 100755
index 00000000000..e046efdf0a3
--- /dev/null
+++ b/exec/install-sh
@@ -0,0 +1,541 @@
1#!/usr/bin/sh
2# install - install a program, script, or datafile
3
4scriptversion=2020-11-14.01; # UTC
5
6# This originates from X11R5 (mit/util/scripts/install.sh), which was
7# later released in X11R6 (xc/config/util/install.sh) with the
8# following copyright and license.
9#
10# Copyright (C) 1994 X Consortium
11#
12# Permission is hereby granted, free of charge, to any person obtaining a copy
13# of this software and associated documentation files (the "Software"), to
14# deal in the Software without restriction, including without limitation the
15# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16# sell copies of the Software, and to permit persons to whom the Software is
17# furnished to do so, subject to the following conditions:
18#
19# The above copyright notice and this permission notice shall be included in
20# all copies or substantial portions of the Software.
21#
22# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28#
29# Except as contained in this notice, the name of the X Consortium shall not
30# be used in advertising or otherwise to promote the sale, use or other deal-
31# ings in this Software without prior written authorization from the X Consor-
32# tium.
33#
34#
35# FSF changes to this file are in the public domain.
36#
37# Calling this script install-sh is preferred over install.sh, to prevent
38# 'make' implicit rules from creating a file called install from it
39# when there is no Makefile.
40#
41# This script is compatible with the BSD install script, but was written
42# from scratch.
43
44tab=' '
45nl='
46'
47IFS=" $tab$nl"
48
49# Set DOITPROG to "echo" to test this script.
50
51doit=${DOITPROG-}
52doit_exec=${doit:-exec}
53
54# Put in absolute file names if you don't have them in your path;
55# or use environment vars.
56
57chgrpprog=${CHGRPPROG-chgrp}
58chmodprog=${CHMODPROG-chmod}
59chownprog=${CHOWNPROG-chown}
60cmpprog=${CMPPROG-cmp}
61cpprog=${CPPROG-cp}
62mkdirprog=${MKDIRPROG-mkdir}
63mvprog=${MVPROG-mv}
64rmprog=${RMPROG-rm}
65stripprog=${STRIPPROG-strip}
66
67posix_mkdir=
68
69# Desired mode of installed file.
70mode=0755
71
72# Create dirs (including intermediate dirs) using mode 755.
73# This is like GNU 'install' as of coreutils 8.32 (2020).
74mkdir_umask=22
75
76backupsuffix=
77chgrpcmd=
78chmodcmd=$chmodprog
79chowncmd=
80mvcmd=$mvprog
81rmcmd="$rmprog -f"
82stripcmd=
83
84src=
85dst=
86dir_arg=
87dst_arg=
88
89copy_on_change=false
90is_target_a_directory=possibly
91
92usage="\
93Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
94 or: $0 [OPTION]... SRCFILES... DIRECTORY
95 or: $0 [OPTION]... -t DIRECTORY SRCFILES...
96 or: $0 [OPTION]... -d DIRECTORIES...
97
98In the 1st form, copy SRCFILE to DSTFILE.
99In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
100In the 4th, create DIRECTORIES.
101
102Options:
103 --help display this help and exit.
104 --version display version info and exit.
105
106 -c (ignored)
107 -C install only if different (preserve data modification time)
108 -d create directories instead of installing files.
109 -g GROUP $chgrpprog installed files to GROUP.
110 -m MODE $chmodprog installed files to MODE.
111 -o USER $chownprog installed files to USER.
112 -p pass -p to $cpprog.
113 -s $stripprog installed files.
114 -S SUFFIX attempt to back up existing files, with suffix SUFFIX.
115 -t DIRECTORY install into DIRECTORY.
116 -T report an error if DSTFILE is a directory.
117
118Environment variables override the default commands:
119 CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
120 RMPROG STRIPPROG
121
122By default, rm is invoked with -f; when overridden with RMPROG,
123it's up to you to specify -f if you want it.
124
125If -S is not specified, no backups are attempted.
126
127Email bug reports to bug-automake@gnu.org.
128Automake home page: https://www.gnu.org/software/automake/
129"
130
131while test $# -ne 0; do
132 case $1 in
133 -c) ;;
134
135 -C) copy_on_change=true;;
136
137 -d) dir_arg=true;;
138
139 -g) chgrpcmd="$chgrpprog $2"
140 shift;;
141
142 --help) echo "$usage"; exit $?;;
143
144 -m) mode=$2
145 case $mode in
146 *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
147 echo "$0: invalid mode: $mode" >&2
148 exit 1;;
149 esac
150 shift;;
151
152 -o) chowncmd="$chownprog $2"
153 shift;;
154
155 -p) cpprog="$cpprog -p";;
156
157 -s) stripcmd=$stripprog;;
158
159 -S) backupsuffix="$2"
160 shift;;
161
162 -t)
163 is_target_a_directory=always
164 dst_arg=$2
165 # Protect names problematic for 'test' and other utilities.
166 case $dst_arg in
167 -* | [=\(\)!]) dst_arg=./$dst_arg;;
168 esac
169 shift;;
170
171 -T) is_target_a_directory=never;;
172
173 --version) echo "$0 $scriptversion"; exit $?;;
174
175 --) shift
176 break;;
177
178 -*) echo "$0: invalid option: $1" >&2
179 exit 1;;
180
181 *) break;;
182 esac
183 shift
184done
185
186# We allow the use of options -d and -T together, by making -d
187# take the precedence; this is for compatibility with GNU install.
188
189if test -n "$dir_arg"; then
190 if test -n "$dst_arg"; then
191 echo "$0: target directory not allowed when installing a directory." >&2
192 exit 1
193 fi
194fi
195
196if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
197 # When -d is used, all remaining arguments are directories to create.
198 # When -t is used, the destination is already specified.
199 # Otherwise, the last argument is the destination. Remove it from $@.
200 for arg
201 do
202 if test -n "$dst_arg"; then
203 # $@ is not empty: it contains at least $arg.
204 set fnord "$@" "$dst_arg"
205 shift # fnord
206 fi
207 shift # arg
208 dst_arg=$arg
209 # Protect names problematic for 'test' and other utilities.
210 case $dst_arg in
211 -* | [=\(\)!]) dst_arg=./$dst_arg;;
212 esac
213 done
214fi
215
216if test $# -eq 0; then
217 if test -z "$dir_arg"; then
218 echo "$0: no input file specified." >&2
219 exit 1
220 fi
221 # It's OK to call 'install-sh -d' without argument.
222 # This can happen when creating conditional directories.
223 exit 0
224fi
225
226if test -z "$dir_arg"; then
227 if test $# -gt 1 || test "$is_target_a_directory" = always; then
228 if test ! -d "$dst_arg"; then
229 echo "$0: $dst_arg: Is not a directory." >&2
230 exit 1
231 fi
232 fi
233fi
234
235if test -z "$dir_arg"; then
236 do_exit='(exit $ret); exit $ret'
237 trap "ret=129; $do_exit" 1
238 trap "ret=130; $do_exit" 2
239 trap "ret=141; $do_exit" 13
240 trap "ret=143; $do_exit" 15
241
242 # Set umask so as not to create temps with too-generous modes.
243 # However, 'strip' requires both read and write access to temps.
244 case $mode in
245 # Optimize common cases.
246 *644) cp_umask=133;;
247 *755) cp_umask=22;;
248
249 *[0-7])
250 if test -z "$stripcmd"; then
251 u_plus_rw=
252 else
253 u_plus_rw='% 200'
254 fi
255 cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
256 *)
257 if test -z "$stripcmd"; then
258 u_plus_rw=
259 else
260 u_plus_rw=,u+rw
261 fi
262 cp_umask=$mode$u_plus_rw;;
263 esac
264fi
265
266for src
267do
268 # Protect names problematic for 'test' and other utilities.
269 case $src in
270 -* | [=\(\)!]) src=./$src;;
271 esac
272
273 if test -n "$dir_arg"; then
274 dst=$src
275 dstdir=$dst
276 test -d "$dstdir"
277 dstdir_status=$?
278 # Don't chown directories that already exist.
279 if test $dstdir_status = 0; then
280 chowncmd=""
281 fi
282 else
283
284 # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
285 # might cause directories to be created, which would be especially bad
286 # if $src (and thus $dsttmp) contains '*'.
287 if test ! -f "$src" && test ! -d "$src"; then
288 echo "$0: $src does not exist." >&2
289 exit 1
290 fi
291
292 if test -z "$dst_arg"; then
293 echo "$0: no destination specified." >&2
294 exit 1
295 fi
296 dst=$dst_arg
297
298 # If destination is a directory, append the input filename.
299 if test -d "$dst"; then
300 if test "$is_target_a_directory" = never; then
301 echo "$0: $dst_arg: Is a directory" >&2
302 exit 1
303 fi
304 dstdir=$dst
305 dstbase=`basename "$src"`
306 case $dst in
307 */) dst=$dst$dstbase;;
308 *) dst=$dst/$dstbase;;
309 esac
310 dstdir_status=0
311 else
312 dstdir=`dirname "$dst"`
313 test -d "$dstdir"
314 dstdir_status=$?
315 fi
316 fi
317
318 case $dstdir in
319 */) dstdirslash=$dstdir;;
320 *) dstdirslash=$dstdir/;;
321 esac
322
323 obsolete_mkdir_used=false
324
325 if test $dstdir_status != 0; then
326 case $posix_mkdir in
327 '')
328 # With -d, create the new directory with the user-specified mode.
329 # Otherwise, rely on $mkdir_umask.
330 if test -n "$dir_arg"; then
331 mkdir_mode=-m$mode
332 else
333 mkdir_mode=
334 fi
335
336 posix_mkdir=false
337 # The $RANDOM variable is not portable (e.g., dash). Use it
338 # here however when possible just to lower collision chance.
339 tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
340
341 trap '
342 ret=$?
343 rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
344 exit $ret
345 ' 0
346
347 # Because "mkdir -p" follows existing symlinks and we likely work
348 # directly in world-writeable /tmp, make sure that the '$tmpdir'
349 # directory is successfully created first before we actually test
350 # 'mkdir -p'.
351 if (umask $mkdir_umask &&
352 $mkdirprog $mkdir_mode "$tmpdir" &&
353 exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
354 then
355 if test -z "$dir_arg" || {
356 # Check for POSIX incompatibilities with -m.
357 # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
358 # other-writable bit of parent directory when it shouldn't.
359 # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
360 test_tmpdir="$tmpdir/a"
361 ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
362 case $ls_ld_tmpdir in
363 d????-?r-*) different_mode=700;;
364 d????-?--*) different_mode=755;;
365 *) false;;
366 esac &&
367 $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
368 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
369 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
370 }
371 }
372 then posix_mkdir=:
373 fi
374 rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
375 else
376 # Remove any dirs left behind by ancient mkdir implementations.
377 rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
378 fi
379 trap '' 0;;
380 esac
381
382 if
383 $posix_mkdir && (
384 umask $mkdir_umask &&
385 $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
386 )
387 then :
388 else
389
390 # mkdir does not conform to POSIX,
391 # or it failed possibly due to a race condition. Create the
392 # directory the slow way, step by step, checking for races as we go.
393
394 case $dstdir in
395 /*) prefix='/';;
396 [-=\(\)!]*) prefix='./';;
397 *) prefix='';;
398 esac
399
400 oIFS=$IFS
401 IFS=/
402 set -f
403 set fnord $dstdir
404 shift
405 set +f
406 IFS=$oIFS
407
408 prefixes=
409
410 for d
411 do
412 test X"$d" = X && continue
413
414 prefix=$prefix$d
415 if test -d "$prefix"; then
416 prefixes=
417 else
418 if $posix_mkdir; then
419 (umask $mkdir_umask &&
420 $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
421 # Don't fail if two instances are running concurrently.
422 test -d "$prefix" || exit 1
423 else
424 case $prefix in
425 *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
426 *) qprefix=$prefix;;
427 esac
428 prefixes="$prefixes '$qprefix'"
429 fi
430 fi
431 prefix=$prefix/
432 done
433
434 if test -n "$prefixes"; then
435 # Don't fail if two instances are running concurrently.
436 (umask $mkdir_umask &&
437 eval "\$doit_exec \$mkdirprog $prefixes") ||
438 test -d "$dstdir" || exit 1
439 obsolete_mkdir_used=true
440 fi
441 fi
442 fi
443
444 if test -n "$dir_arg"; then
445 { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
446 { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
447 { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
448 test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
449 else
450
451 # Make a couple of temp file names in the proper directory.
452 dsttmp=${dstdirslash}_inst.$$_
453 rmtmp=${dstdirslash}_rm.$$_
454
455 # Trap to clean up those temp files at exit.
456 trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
457
458 # Copy the file name to the temp name.
459 (umask $cp_umask &&
460 { test -z "$stripcmd" || {
461 # Create $dsttmp read-write so that cp doesn't create it read-only,
462 # which would cause strip to fail.
463 if test -z "$doit"; then
464 : >"$dsttmp" # No need to fork-exec 'touch'.
465 else
466 $doit touch "$dsttmp"
467 fi
468 }
469 } &&
470 $doit_exec $cpprog "$src" "$dsttmp") &&
471
472 # and set any options; do chmod last to preserve setuid bits.
473 #
474 # If any of these fail, we abort the whole thing. If we want to
475 # ignore errors from any of these, just make sure not to ignore
476 # errors from the above "$doit $cpprog $src $dsttmp" command.
477 #
478 { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
479 { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
480 { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
481 { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
482
483 # If -C, don't bother to copy if it wouldn't change the file.
484 if $copy_on_change &&
485 old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
486 new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
487 set -f &&
488 set X $old && old=:$2:$4:$5:$6 &&
489 set X $new && new=:$2:$4:$5:$6 &&
490 set +f &&
491 test "$old" = "$new" &&
492 $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
493 then
494 rm -f "$dsttmp"
495 else
496 # If $backupsuffix is set, and the file being installed
497 # already exists, attempt a backup. Don't worry if it fails,
498 # e.g., if mv doesn't support -f.
499 if test -n "$backupsuffix" && test -f "$dst"; then
500 $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
501 fi
502
503 # Rename the file to the real destination.
504 $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
505
506 # The rename failed, perhaps because mv can't rename something else
507 # to itself, or perhaps because mv is so ancient that it does not
508 # support -f.
509 {
510 # Now remove or move aside any old file at destination location.
511 # We try this two ways since rm can't unlink itself on some
512 # systems and the destination file might be busy for other
513 # reasons. In this case, the final cleanup might fail but the new
514 # file should still install successfully.
515 {
516 test ! -f "$dst" ||
517 $doit $rmcmd "$dst" 2>/dev/null ||
518 { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
519 { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
520 } ||
521 { echo "$0: cannot unlink or rename $dst" >&2
522 (exit 1); exit 1
523 }
524 } &&
525
526 # Now rename the file to the real destination.
527 $doit $mvcmd "$dsttmp" "$dst"
528 }
529 fi || exit 1
530
531 trap '' 0
532 fi
533done
534
535# Local variables:
536# eval: (add-hook 'before-save-hook 'time-stamp)
537# time-stamp-start: "scriptversion="
538# time-stamp-format: "%:y-%02m-%02d.%02H"
539# time-stamp-time-zone: "UTC0"
540# time-stamp-end: "; # UTC"
541# End:
diff --git a/exec/loader-aarch64.s b/exec/loader-aarch64.s
new file mode 100644
index 00000000000..da8ec1f4977
--- /dev/null
+++ b/exec/loader-aarch64.s
@@ -0,0 +1,187 @@
1// Copyright (C) 2023 Free Software Foundation, Inc.
2//
3// This file is part of GNU Emacs.
4//
5// GNU Emacs is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published
7// by the Free Software Foundation, either version 3 of the License,
8// or (at your option) any later version.
9//
10// GNU Emacs is distributed in the hope that it will be useful, but
11// WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13// General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
17
18// Notice that aarch64 requires that sp be aligned to 16 bytes while
19// accessing memory from sp, so x20 is used to chase down the load
20// area.
21
22 .section .text
23 .global _start
24_start:
25 //mov x8, 101 // SYS_nanosleep
26 //adr x0, timespec // req
27 //mov x1, #0 // rem
28 //svc #0 // syscall
29 mov x20, sp // x20 = sp
30 ldr x10, [x20] // x10 = original SP
31 add x20, x20, #16 // x20 = start of load area
32 mov x28, #-1 // x28 = secondary fd
33.next_action:
34 ldr x11, [x20] // action number
35 and x12, x11, #-17 // actual action number
36 cbz x12, .open_file // open file?
37 cmp x12, #3 // jump?
38 beq .rest_of_exec
39 cmp x12, #4 // anonymous mmap?
40 beq .do_mmap_anon
41.do_mmap:
42 ldr x0, [x20, 8] // vm_address
43 ldr x1, [x20, 32] // length
44 ldr x2, [x20, 24] // protection
45 ldr x3, [x20, 40] // flags
46 tst x11, #16 // primary fd?
47 mov x4, x29 // primary fd
48 beq .do_mmap_1
49 mov x4, x28 // secondary fd
50.do_mmap_1:
51 mov x8, #222 // SYS_mmap
52 ldr x5, [x20, 16] // file_offset
53 svc #0 // syscall
54 ldr x9, [x20, 8] // length
55 cmp x0, x9 // mmap result
56 bne .perror // print error
57 ldr x3, [x20, 48] // clear
58 add x1, x1, x0 // x1 = vm_address + end
59 sub x3, x1, x3 // x3 = x1 - clear
60 mov x0, #0 // x0 = 0
61.fill64:
62 sub x2, x1, x3 // x2 = x1 - x3
63 cmp x2, #63 // x2 >= 64?
64 ble .fillb // start filling bytes
65 stp x0, x0, [x3] // x3[0] = 0, x3[1] = 0
66 stp x0, x0, [x3, 16] // x3[2] = 0, x3[3] = 0
67 stp x0, x0, [x3, 32] // x3[4] = 0, x3[5] = 0
68 stp x0, x0, [x3, 48] // x3[6] = 0, x3[7] = 0
69 add x3, x3, #64 // x3 += 8
70 b .fill64
71.fillb:
72 cmp x1, x3 // x1 == x3?
73 beq .continue // done
74 strb w0, [x3], #1 // ((char *) x3)++ = 0
75 b .fillb
76.continue:
77 add x20, x20, #56 // next action
78 b .next_action
79.do_mmap_anon:
80 ldr x0, [x20, 8] // vm_address
81 ldr x1, [x20, 32] // length
82 ldr x2, [x20, 24] // protection
83 ldr x3, [x20, 40] // flags
84 mov x4, #-1 // fd
85 b .do_mmap_1
86.open_file:
87 mov x8, #56 // SYS_openat
88 mov x0, #-100 // AT_FDCWD
89 add x1, x20, #8 // file name
90 mov x2, #0 // O_RDONLY
91 mov x3, #0 // mode
92 svc #0 // syscall
93 cmp x0, #-1 // rc < 0?
94 ble .perror
95 mov x19, x1 // x19 == x1
96.nextc:
97 ldrb w2, [x1], #1 // b = *x1++
98 cmp w2, #47 // dir separator?
99 bne .nextc1 // not dir separator
100 mov x19, x1 // x19 = char past separator
101.nextc1:
102 cbnz w2, .nextc // b?
103 add x1, x1, #7 // round up x1
104 and x20, x1, #-8 // mask for round, set x20
105 tst x11, #16 // primary fd?
106 bne .secondary // secondary fd
107 mov x29, x0 // primary fd
108 mov x8, #167 // SYS_prctl
109 mov x0, #15 // PR_SET_NAME
110 mov x1, x19 // basename
111 mov x2, #0 // arg2
112 mov x3, #0 // arg3
113 mov x4, #0 // arg4
114 mov x5, #0 // arg5
115 svc #0 // syscall
116 b .next_action // next action
117.secondary:
118 mov x28, x0 // secondary fd
119 b .next_action // next action.
120.perror:
121 mov x8, #93 // SYS_exit
122 mvn x0, x0 // x1 = ~x0
123 add x0, x0, 1 // x1 += 1
124 svc #0 // exit
125.rest_of_exec:
126 mov x7, x20 // x7 = x20
127 mov x20, x10 // x20 = x10
128 ldr x9, [x20] // argc
129 add x9, x9, #2 // x9 += 2
130 lsl x9, x9, #3 // argc * 8
131 add x20, x20, x9 // now past argv
132.skipenv:
133 ldr x9, [x20], #8 // x9 = *envp++
134 cbnz x9, .skipenv // x9?
135.one_auxv:
136 ldr x9, [x20], #16 // x9 = *sp, sp += 2
137 cbz x9, .cleanup // !x9?
138 cmp x9, #3 // is AT_PHDR?
139 beq .replace_phdr // replace
140 cmp x9, #4 // is AT_PHENT?
141 beq .replace_phent // replace
142 cmp x9, #5 // is AT_PHNUM?
143 beq .replace_phnum // replace
144 cmp x9, #9 // is AT_ENTRY?
145 beq .replace_entry // replace
146 cmp x9, #7 // is AT_BASE?
147 beq .replace_base // replace
148 b .one_auxv // next auxv
149.replace_phdr:
150 ldr x9, [x7, 40] // at_phdr
151 str x9, [x20, -8] // store value
152 b .one_auxv
153.replace_phent:
154 ldr x9, [x7, 24] // at_phent
155 str x9, [x20, -8] // store value
156 b .one_auxv
157.replace_phnum:
158 ldr x9, [x7, 32] // at_phnum
159 str x9, [x20, -8] // store value
160 b .one_auxv
161.replace_entry:
162 ldr x9, [x7, 16] // at_entry
163 str x9, [x20, -8] // store value
164 b .one_auxv
165.replace_base:
166 ldr x9, [x7, 48] // at_base
167 str x9, [x20, -8] // store value
168 b .one_auxv
169.cleanup:
170 cmp x28, #-1 // is secondary fd set?
171 bne .cleanup1 // not set
172 mov x8, #57 // SYS_close
173 mov x0, x28 // secondary fd
174 svc #0 // syscall
175.cleanup1:
176 mov x8, #57 // SYS_close
177 mov x0, x29 // primary fd
178 svc #0 // syscall
179.enter:
180 mov sp, x10 // restore original SP
181 mov x0, #0 // clear rtld_fini
182 ldr x1, [x7, 8] // branch to code
183 br x1
184
185timespec:
186 .quad 10
187 .quad 10
diff --git a/exec/loader-armeabi.s b/exec/loader-armeabi.s
new file mode 100644
index 00000000000..32b2a5268d6
--- /dev/null
+++ b/exec/loader-armeabi.s
@@ -0,0 +1,204 @@
1@ Copyright (C) 2023 Free Software Foundation, Inc.
2@
3@ This file is part of GNU Emacs.
4@
5@ GNU Emacs is free software: you can redistribute it and/or modify
6@ it under the terms of the GNU General Public License as published
7@ by the Free Software Foundation, either version 3 of the License,
8@ or (at your option) any later version.
9@
10@ GNU Emacs is distributed in the hope that it will be useful, but
11@ WITHOUT ANY WARRANTY; without even the implied warranty of
12@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13@ General Public License for more details.
14@
15@ You should have received a copy of the GNU General Public License
16@ along with GNU Emacs. If not, see <https:@www.gnu.org/licenses/>.
17
18 .section .text
19 .global _start
20_start:
21 @mov r7, #162 @ SYS_nanosleep
22 @adr r0, timespec @ req
23 @mov r1, #0 @ rem
24 @swi #0 @ syscall
25 mov r8, sp @ r8 = sp
26 ldr r9, [r8], #8 @ r9 = original sp, r8 += 8
27 mov r14, #-1 @ r14 = secondary fd
28.next_action:
29 ldr r11, [r8] @ r11 = action number
30 and r12, r11, #-17 @ actual action number
31 cmp r12, #0 @ open file?
32 beq .open_file @ open file.
33 cmp r12, #3 @ jump?
34 beq .rest_of_exec @ jump to code.
35 cmp r12, #4 @ anonymous mmap?
36 beq .do_mmap_anon @ anonymous mmap.
37.do_mmap:
38 add r6, r8, #4 @ r6 = r8 + 4
39 ldm r6!, {r0, r5} @ vm_address, file_offset
40 ldm r6!, {r1, r2} @ protection, length
41 mov r3, r1 @ swap
42 lsr r5, #12 @ divide file offset by page size
43 mov r1, r2 @ swap
44 mov r2, r3 @ swap
45 ldm r6!, {r3, r12} @ flags, clear
46 tst r11, #16 @ primary fd?
47 mov r4, r10 @ primary fd
48 beq .do_mmap_1
49 mov r4, r14 @ secondary fd
50.do_mmap_1:
51 mov r7, #192 @ SYS_mmap2
52 swi #0 @ syscall
53 ldr r2, [r8, #4] @ vm_address
54 cmp r2, r0 @ rc == vm_address?
55 bne .perror
56 add r0, r1, r2 @ r0 = length + vm_address
57 sub r3, r0, r12 @ r3 = r0 - clear
58 mov r1, #0 @ r1 = 0
59.align:
60 cmp r0, r3 @ r0 == r3?
61 beq .continue @ continue
62 tst r3, #3 @ r3 & 3?
63 bne .fill32 @ fill aligned
64 strb r1, [r3], #1 @ fill byte
65 b .align @ align again
66.fill32:
67 sub r2, r0, r3 @ r2 = r0 - r3
68 cmp r2, #31 @ r2 >= 32?
69 ble .fillb @ start filling bytes
70 str r1, [r3], #4 @ *r3++ = 0
71 str r1, [r3], #4 @ *r3++ = 0
72 str r1, [r3], #4 @ *r3++ = 0
73 str r1, [r3], #4 @ *r3++ = 0
74 str r1, [r3], #4 @ *r3++ = 0
75 str r1, [r3], #4 @ *r3++ = 0
76 str r1, [r3], #4 @ *r3++ = 0
77 str r1, [r3], #4 @ *r3++ = 0
78 b .fill32
79.fillb:
80 cmp r0, r3 @ r0 == r3
81 beq .continue @ done
82 strb r1, [r3], #1 @ ((char *) r3)++ = 0
83 b .fillb
84.continue:
85 add r8, r8, #28 @ next action
86 b .next_action
87.do_mmap_anon:
88 add r6, r8, #4 @ r6 = r8 + 4
89 ldm r6!, {r0, r5} @ vm_address, file_offset
90 ldm r6!, {r1, r2} @ protection, length
91 mov r3, r1 @ swap
92 lsr r5, #12 @ divide file offset by page size
93 mov r1, r2 @ swap
94 mov r2, r3 @ swap
95 ldm r6!, {r3, r12} @ flags, clear
96 mov r4, #-1 @ fd
97 b .do_mmap_1
98.open_file:
99 mov r7, #5 @ SYS_open
100 add r0, r8, #4 @ file name
101 mov r1, #0 @ O_RDONLY
102 mov r2, #0 @ mode
103 swi #0 @ syscall
104 cmp r0, #-1 @ r0 <= -1?
105 ble .perror
106 add r8, r8, #4 @ r8 = start of string
107 mov r1, r8 @ r1 = r8
108.nextc:
109 ldrb r2, [r8], #1 @ b = *r0++
110 cmp r2, #47 @ dir separator?
111 bne .nextc1 @ not dir separator
112 mov r1, r8 @ r1 = char past separator
113.nextc1:
114 cmp r2, #0 @ b?
115 bne .nextc @ next character
116 add r8, r8, #3 @ round up r8
117 and r8, r8, #-4 @ mask for round, set r8
118 tst r11, #16 @ primary fd?
119 bne .secondary @ secondary fd
120 mov r10, r0 @ primary fd
121 mov r7, #172 @ SYS_prctl
122 mov r0, #15 @ PR_SET_NAME, r1 = name
123 mov r2, #0 @ arg2
124 mov r3, #0 @ arg3
125 mov r4, #0 @ arg4
126 mov r5, #0 @ arg5
127 swi #0 @ syscall
128 b .next_action @ next action
129.secondary:
130 mov r14, r0 @ secondary fd
131 b .next_action @ next action
132.perror:
133 mov r7, #1 @ SYS_exit
134 mvn r0, r0 @ r0 = ~r0
135 add r0, r0, #1 @ r0 += 1
136 swi #0
137.rest_of_exec:
138 mov r7, r9 @ r7 = original SP
139 ldr r6, [r7] @ argc
140 add r6, r6, #2 @ argc + 2
141 lsl r6, r6, #2 @ argc *= 4
142 add r7, r7, r6 @ now past argv
143.skipenv:
144 ldr r6, [r7], #4 @ r6 = *r7++
145 cmp r6, #0 @ r6?
146 bne .skipenv @ r6?
147.one_auxv:
148 ldr r6, [r7], #8 @ r6 = *r7, r7 += 2
149 cmp r6, #0 @ !r6?
150 beq .cleanup @ r6?
151 cmp r6, #3 @ is AT_PHDR?
152 beq .replace_phdr @ replace
153 cmp r6, #4 @ is AT_PHENT?
154 beq .replace_phent @ replace
155 cmp r6, #5 @ is AT_PHNUM?
156 beq .replace_phnum @ replace
157 cmp r6, #9 @ is AT_ENTRY?
158 beq .replace_entry @ replace
159 cmp r6, #7 @ is AT_BASE?
160 beq .replace_base @ replace
161 b .one_auxv @ next auxv
162.replace_phdr:
163 ldr r6, [r8, #20] @ at_phdr
164 str r6, [r7, #-4] @ store value
165 b .one_auxv
166.replace_phent:
167 ldr r6, [r8, #12] @ at_phent
168 str r6, [r7, #-4] @ store value
169 b .one_auxv
170.replace_phnum:
171 ldr r6, [r8, #16] @ at_phnum
172 str r6, [r7, #-4] @ store value
173 b .one_auxv
174.replace_entry:
175 ldr r6, [r8, #8] @ at_entry
176 str r6, [r7, #-4] @ store value
177 b .one_auxv
178.replace_base:
179 ldr r6, [r8, #24] @ at_base
180 str r6, [r7, #-4] @ store value
181 b .one_auxv
182.cleanup:
183 cmp r14, #-1 @ secondary fd set?
184 bne .cleanup1 @ not set
185 mov r7, #6 @ SYS_close
186 mov r0, r14 @ secondary fd
187 swi #0 @ syscall
188.cleanup1:
189 mov r7, #6 @ SYS_close
190 mov r0, r10 @ primary fd
191 swi #0 @ syscall
192.enter:
193 mov sp, r9 @ restore original SP
194 mov r0, #0 @ clear rtld_fini
195 ldr r1, [r8, #4] @ branch to code
196 bx r1
197
198timespec:
199 .long 10
200 .long 10
201
202@ Local Variables:
203@ asm-comment-char: 64
204@ End:
diff --git a/exec/loader-mips64el.s b/exec/loader-mips64el.s
new file mode 100644
index 00000000000..f4a6f918497
--- /dev/null
+++ b/exec/loader-mips64el.s
@@ -0,0 +1,234 @@
1# Copyright (C) 2023 Free Software Foundation, Inc.
2#
3# This file is part of GNU Emacs.
4#
5# GNU Emacs is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published
7# by the Free Software Foundation, either version 3 of the License,
8# or (at your option) any later version.
9#
10# GNU Emacs is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13# General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
17
18include(`config-mips.m4')
19
20 .set noreorder # delay slots managed by hand
21 .set noat # no assembler macros
22 .section .text
23 .global __start
24__start:
25dnl li $v0, 5034 # SYS_nanosleep
26dnl dla $a0, .timespec # rqtp
27dnl li $a1, 0 # rmtp
28dnl syscall # syscall
29 ld $s2, ($sp) # original stack pointer
30 DADDI3( $s0, $sp, 16) # start of load area
31 DADDI2( $sp, -16) # primary fd, secondary fd
32 li $t0, -1 # secondary fd
33 sd $t0, 8($sp) # initialize secondary fd
34.next_action:
35 ld $s1, ($s0) # action number
36 andi $t0, $s1, 15 # t0 = action number & 15
37 beqz $t0, .open_file # open file?
38 nop # delay slot
39 DADDI2( $t0, -3) # t0 -= 3
40 beqz $t0, .rest_of_exec # jump to code
41 nop # delay slot
42 li $t1, 1
43 beq $t0, $t1, .do_mmap_anon # anonymous mmap?
44 nop # delay slot
45.do_mmap:
46 ld $t0, 8($s0) # vm address
47 ld $t1, 16($s0) # file_offset
48 ld $t2, 24($s0) # protection
49 ld $t3, 32($s0) # length
50 ld $v0, 40($s0) # flags
51 ld $v1, ($sp) # primary fd
52 andi $s3, $s1, 16 # s1 & 16?
53 beqz $s3, .do_mmap_1 # secondary fd?
54 nop # delay slot
55 ld $v1, 8($sp) # secondary fd
56.do_mmap_1:
57 move $a0, $t0 # syscall arg
58 move $a1, $t3 # syscall arg
59 move $a2, $t2 # syscall arg
60 move $a3, $v0 # syscall arg
61 move $a4, $v1 # syscall arg
62 move $a5, $t1 # syscall arg
63 li $v0, 5009 # SYS_mmap
64 syscall # syscall
65 bne $a3, $zero, .perror # perror?
66 nop # delay slot
67 ld $t1, 48($s0) # clear
68 dadd $t0, $a0, $a1 # t0 = end of mapping
69 dsub $t1, $t0, $t1 # t1 = t0 - clear
70.align:
71 beq $t0, $t1, .continue # already finished
72 nop # delay slot
73 andi $t2, $t1, 7 # t1 & 7?
74 bnez $t2, .filld # start filling longs
75 nop # delay slot
76.filld:
77 dsub $t2, $t0, $t1 # t2 = t0 - t1
78 sltiu $t2, $t2, 64 # t2 < 64?
79 bne $t2, $zero, .fillb # fill bytes
80 nop # delay slot
81 sd $zero, ($t1) # zero doubleword
82 DADDI2( $t1, 8) # next doubleword
83 sd $zero, ($t1) # zero doubleword
84 DADDI2( $t1, 8) # next doubleword
85 sd $zero, ($t1) # zero doubleword
86 DADDI2( $t1, 8) # next doubleword
87 sd $zero, ($t1) # zero doubleword
88 DADDI2( $t1, 8) # next doubleword
89 sd $zero, ($t1) # zero doubleword
90 DADDI2( $t1, 8) # next doubleword
91 sd $zero, ($t1) # zero doubleword
92 DADDI2( $t1, 8) # next doubleword
93 sd $zero, ($t1) # zero doubleword
94 DADDI2( $t1, 8) # next doubleword
95 sd $zero, ($t1) # zero doubleword
96 DADDI2( $t1, 8) # next doubleword
97 j .filld # fill either doubleword or byte
98 nop # delay slot
99.fillb:
100 beq $t0, $t1, .continue # already finished?
101 nop # delay slot
102 sb $zero, ($t1) # clear byte
103 DADDI2( $t1, 1) # t1++
104.continue:
105 DADDI2( $s0, 56) # s0 = next action
106 j .next_action # next action
107 nop # delay slot
108.do_mmap_anon:
109 ld $t0, 8($s0) # vm address
110 ld $t1, 16($s0) # file_offset
111 ld $t2, 24($s0) # protection
112 ld $t3, 32($s0) # length
113 ld $v0, 40($s0) # flags
114 li $v1, -1 # fd
115 j .do_mmap_1 # do mmap
116 nop # branch delay slot
117.open_file:
118 li $v0, 5002 # SYS_open
119 DADDI3( $a0, $s0, 8) # start of name
120 move $a1, $zero # flags = O_RDONLY
121 move $a2, $zero # mode = 0
122 syscall # syscall
123 bne $a3, $zero, .perror # perror
124 nop # delay slot
125 DADDI2( $s0, 8) # start of string
126 move $t3, $s0 # t3 = s0
127.nextc:
128 lb $t0, ($s0) # load byte
129 DADDI2( $s0, 1) # s0++
130 li $t1, 47 # directory separator `/'
131 bne $t0, $t1, .nextc1 # is separator char?
132 nop # delay slot
133 move $t3, $s0 # t3 = char past separator
134.nextc1:
135 bnez $t0, .nextc # next character?
136 nop # delay slot
137 DADDI2( $s0, 7) # adjust for round
138 li $t2, -8 # t2 = -8
139 and $s0, $s0, $t2 # mask for round
140 andi $t0, $s1, 16 # t1 = s1 & 16
141 move $t1, $sp # address of primary fd
142 beqz $t0, .primary # primary fd?
143 nop # delay slot
144 DADDI2( $t1, 8) # address of secondary fd
145 sd $v0, ($t1) # store fd
146 j .next_action # next action
147 nop # delay slot
148.primary:
149 sd $v0, ($t1) # store fd
150 li $v0, 5153 # SYS_prctl
151 li $a0, 15 # PR_SET_NAME
152 move $a1, $t3 # char past separator
153 move $a2, $zero # a2
154 move $a3, $zero # a3
155 move $a4, $zero # a4
156 move $a5, $zero # a5
157 syscall # syscall
158 j .next_action # next action
159 nop # delay slot
160.perror:
161 move $a0, $v0 # errno
162 li $v0, 5058 # SYS_exit
163 syscall # syscall
164.rest_of_exec:
165 move $s1, $s2 # original SP
166 ld $t0, ($s1) # argc
167 dsll $t0, $t0, 3 # argc *= 8
168 DADDI2( $t0, 16) # argc += 16
169 dadd $s1, $s1, $t0 # s1 = start of envp
170.skipenv:
171 ld $t0, ($s1) # t0 = *s1
172 DADDI2( $s1, 8) # s1++
173 bne $t0, $zero, .skipenv # skip again
174 nop # delay slot
175 dla $t3, .auxvtab # address of auxv table
176.one_auxv:
177 ld $t0, ($s1) # t0 = auxv type
178 li $t1, 10 # t1 = 10
179 beqz $t0, .finish # is AT_IGNORE?
180 nop # delay slot
181 sltu $t1, $t0, $t1 # t1 = t0 < num offsets
182 beqz $t1, .next # next auxv
183 nop # delay slot
184 dsll $t1, $t0, 2 # t1 = t0 * 4
185 dadd $t1, $t3, $t1 # t1 = .auxvtab + t1
186 lw $t2, ($t1) # t2 = *t1
187 beqz $t2, .next # skip auxv
188 nop # delay slot
189 dadd $t2, $s0, $t2 # t2 = s0 + t2
190 ld $t2, ($t2) # t2 = *t2
191 sd $t2, 8($s1) # set auxv value
192.next:
193 DADDI2( $s1, 16) # next auxv
194 j .one_auxv # next auxv
195 nop # delay slot
196.finish:
197 ld $t0, 8($sp) # secondary fd
198 li $t1, -1 # t1 = -1
199 ld $s1, ($sp) # s1 = primary fd
200 li $v0, 5003 # SYS_close
201 beq $t0, $t2, .finish1 # secondary fd set?
202 nop # delay slot
203 move $a0, $t0 # secondary fd
204 syscall # syscall
205 li $v0, 5003 # SYS_close
206.finish1:
207 move $a0, $s1 # primary fd
208 syscall # syscall
209.jump:
210 move $v0, $zero # rtld_fini
211 ld $t0, 8($s0) # entry
212 move $sp, $s2 # restore stack pointer, delay slot
213 jr $t0 # enter
214 nop # delay slot
215
216.auxvtab:
217 .long 0 # 0
218 .long 0 # 1
219 .long 0 # 2
220 .long 40 # 3 AT_PHDR
221 .long 24 # 4 AT_PHENT
222 .long 32 # 5 AT_PHNUM
223 .long 0 # 6
224 .long 48 # 7 AT_BASE
225 .long 0 # 8
226 .long 16 # 9 AT_ENTRY
227
228.timespec:
229 .quad 10
230 .quad 10
231
232# Local Variables:
233# asm-comment-char: 35
234# End:
diff --git a/exec/loader-mipsel.s b/exec/loader-mipsel.s
new file mode 100644
index 00000000000..baba3f05a94
--- /dev/null
+++ b/exec/loader-mipsel.s
@@ -0,0 +1,236 @@
1# Copyright (C) 2023 Free Software Foundation, Inc.
2#
3# This file is part of GNU Emacs.
4#
5# GNU Emacs is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published
7# by the Free Software Foundation, either version 3 of the License,
8# or (at your option) any later version.
9#
10# GNU Emacs is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13# General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
17
18include(`config-mips.m4')
19
20# Make sure not to use t4 through t7, in order to maintain portability
21# with N32 ABI systems.
22
23 .set noreorder # delay slots managed by hand
24 .section .text
25 .global __start
26__start:
27dnl li $v0, SYSCALL_nanosleep # SYS_nanosleep
28dnl la $a0, .timespec # rqtp
29dnl li $a1, 0 # rmtp
30dnl syscall # syscall
31 lw $s6, ($sp) # original stack pointer
32 addi $s0, $sp, 8 # start of load area
33 addi $sp, -8 # primary fd, secondary fd
34 li $t0, -1 # secondary fd
35 sw $t0, 4($sp) # initialize secondary fd
36.next_action:
37 lw $s2, ($s0) # action number
38 nop # delay slot
39 andi $t0, $s2, 15 # t0 = s2 & 15
40 beqz $t0, .open_file # open file?
41 li $t1, 3 # t1 = 3, delay slot
42 beq $t0, $t1, .rest_of_exec # jump to code
43 li $t1, 4 # t1 = 4, delay slot
44 beq $t0, $t1, .do_mmap_anon # anonymous mmap
45.do_mmap:
46 lw $a0, 4($s0) # vm_address, delay slot
47 lw $v1, 8($s0) # file_offset
48 lw $a2, 12($s0) # protection
49 lw $a1, 16($s0) # length
50 lw $a3, 20($s0) # flags
51 lw $v0, ($sp) # primary fd
52 andi $t1, $s2, 16 # t1 = s2 & 16
53 beqz $t1, .do_mmap_1 # secondary fd?
54 nop # delay slot
55 lw $v0, 4($sp) # secondary fd
56 nop # delay slot
57.do_mmap_1:
58SYSCALL(`$v0',`$v1',`$zero',`$zero') # syscall args
59 li $v0, SYSCALL_mmap # SYS_mmap
60 syscall # syscall
61 bne $a3, $zero, .perror # perror
62RESTORE() # delay slot, restore sp
63 lw $s5, 24($s0) # clear
64 add $t0, $a0, $a1 # t0 = length + vm_address, delay slot
65 sub $t1, $t0, $s5 # t1 = t0 - clear
66.align:
67 beq $t0, $t1, .continue # already finished?
68 nop # delay slot
69 andi $t2, $t1, 3 # t1 & 3?
70 bnez $t2, .fillw # start filling longs
71 nop # delay slot
72 sb $zero, ($t1) # clear byte
73 addi $t1, $t1, 1 # t1++
74 j .align # continue
75 nop # delay slot
76.fillw:
77 sub $t2, $t0, $t1 # t2 = t0 - t1
78 sltiu $t2, $t2, 32 # r2 < 32?
79 bne $t2, $zero, .fillb # fill bytes
80 nop # delay slot
81 sw $zero, ($t1) # zero word
82 addi $t1, $t1, 4 # next word
83 sw $zero, ($t1) # zero word
84 addi $t1, $t1, 4 # next word
85 sw $zero, ($t1) # zero word
86 addi $t1, $t1, 4 # next word
87 sw $zero, ($t1) # zero word
88 addi $t1, $t1, 4 # next word
89 sw $zero, ($t1) # zero word
90 addi $t1, $t1, 4 # next word
91 sw $zero, ($t1) # zero word
92 addi $t1, $t1, 4 # next word
93 sw $zero, ($t1) # zero word
94 addi $t1, $t1, 4 # next word
95 sw $zero, ($t1) # zero word
96 addi $t1, $t1, 4 # next word
97 j .fillw # fill either word or byte
98 nop # delay slot
99.fillb:
100 beq $t0, $t1, .continue # already finished?
101 nop # delay slot
102 sb $zero, ($t1) # clear byte
103 addi $t1, $t1, 1 # t1++
104.continue:
105 addi $s0, $s0, 28 # s0 = next action
106 j .next_action # next action
107 nop # delay slot
108.do_mmap_anon:
109 lw $v1, 8($s0) # file_offset
110 lw $a2, 12($s0) # protection
111 lw $a1, 16($s0) # length
112 lw $a3, 20($s0) # flags
113 li $t4, -1 # fd
114 j .do_mmap_1 # do mmap
115 nop # delay slot
116.open_file:
117 li $v0, SYSCALL_open # SYS_open
118 addi $a0, $s0, 4 # start of name
119 move $a1, $zero # flags = O_RDONLY
120 move $a2, $zero # mode = 0
121 syscall # syscall
122 bne $a3, $zero, .perror # perror
123 addi $s0, $s0, 4 # start of string, delay slot
124 move $t3, $s0 # t3 = char past separator
125.nextc:
126 lb $t0, ($s0) # load byte
127 addi $s0, $s0, 1 # s0++
128 li $t1, 47 # directory separator `/'
129 bne $t0, $t1, .nextc1 # is separator char?
130 nop # delay slot
131 move $t3, $s0 # t3 = char past separator
132.nextc1:
133 bnez $t0, .nextc # next character?
134 nop # delay slot
135 addi $s0, $s0, 3 # adjust for round
136 li $t2, -4 # t2 = -4
137 and $s0, $s0, $t2 # mask for round
138 andi $t0, $s2, 16 # t1 = s2 & 16
139 beqz $t0, .primary # primary fd?
140 move $t0, $sp # address of primary fd, delay slot
141 addi $t0, $t0, 4 # address of secondary fd
142 j .next_action # next action
143.primary:
144 sw $v0, ($t0) # store fd, delay slot
145 li $v0, SYSCALL_prctl # SYS_prctl
146 li $a0, 15 # PR_SET_NAME
147 move $a1, $t3 # name
148 move $a2, $zero # arg1
149 move $a3, $zero # arg2
150SYSCALL(`$a2',`$a2',`$a2',`$a2') # syscall args
151 syscall # syscall
152RESTORE() # restore sp
153 j .next_action # next action
154 nop # delay slot
155.perror:
156 move $a0, $v0 # errno
157 li $v0, SYSCALL_exit # SYS_exit
158 syscall # syscall
159.rest_of_exec:
160 move $s1, $s6 # s1 = original SP
161 lw $t0, ($s1) # argc
162 nop # delay slot
163 sll $t0, $t0, 2 # argc *= 4
164 addi $t0, $t0, 8 # argc += 8
165 add $s1, $s1, $t0 # s1 = start of envp
166.skipenv:
167 lw $t0, ($s1) # t0 = *s1
168 addi $s1, $s1, 4 # s1++
169 bne $t0, $zero, .skipenv # skip again
170 nop # delay slot
171 la $s2, .auxvtab # address of auxv table
172.one_auxv:
173 lw $t0, ($s1) # t0 = auxv type
174 li $t1, 10 # t1 = 10, delay slot
175 beqz $t0, .finish # is AT_IGNORE?
176 sltu $t1, $t0, $t1 # t1 = t0 < num offsets, delay slot
177 beq $t1, $zero, .next # next auxv
178 sll $t1, $t0, 2 # t1 = t0 * 4, delay slot
179 add $t1, $s2, $t1 # t1 = .auxvtab + t1
180 lw $t2, ($t1) # t2 = *t1
181 nop # delay slot
182 beqz $t2, .next # skip auxv
183 add $t2, $s0, $t2 # t2 = s0 + t2
184 lw $t2, ($t2) # t2 = *t2
185 nop # delay slot
186 sw $t2, 4($s1) # set auxv value
187.next:
188 addi $s1, $s1, 8 # next auxv
189 j .one_auxv # next auxv
190 nop # delay slot
191.finish:
192 lw $t0, 4($sp) # secondary fd
193 lw $s1, ($sp) # primary fd, delay slot, preserved
194 li $t2, -1 # immediate -1
195 beq $t0, $t2, .finish1 # secondary fd set?
196 li $v0, SYSCALL_close # SYS_close, delay slot
197 move $a0, $t0 # fd
198 syscall # syscall
199 li $v0, SYSCALL_close # SYS_close
200.finish1:
201 move $a0, $s1 # primary fd
202 syscall # syscall
203 li $v0, SYSCALL_prctl # SYS_prctl
204 li $a0, 45 # PR_SET_FP_MODE
205 lw $a1, 28($s0) # fpu_mode
206 move $a2, $zero # arg3
207 move $a3, $zero # arg4
208SYSCALL(`$a2',`$a2',`$a2',`$a2') # syscall args
209 syscall # syscall
210RESTORE() # restore sp
211.jump:
212 move $v0, $zero # rtld_fini
213 lw $t0, 4($s0) # entry
214 move $sp, $s6 # restore stack pointer, delay slot
215 jr $t0 # enter
216 nop # delay slot
217
218.auxvtab:
219 .long 0 # 0
220 .long 0 # 1
221 .long 0 # 2
222 .long 20 # 3 AT_PHDR
223 .long 12 # 4 AT_PHENT
224 .long 16 # 5 AT_PHNUM
225 .long 0 # 6
226 .long 24 # 7 AT_BASE
227 .long 0 # 8
228 .long 8 # 9 AT_ENTRY
229
230.timespec:
231 .long 10
232 .long 10
233
234# Local Variables:
235# asm-comment-char: 35
236# End:
diff --git a/exec/loader-x86.s b/exec/loader-x86.s
new file mode 100644
index 00000000000..6329e7f33b1
--- /dev/null
+++ b/exec/loader-x86.s
@@ -0,0 +1,203 @@
1define(`CC', `
2dnl')
3
4CC Copyright (C) 2023 Free Software Foundation, Inc.
5CC
6CC This file is part of GNU Emacs.
7CC
8CC GNU Emacs is free software: you can redistribute it and/or modify
9CC it under the terms of the GNU General Public License as published
10CC by the Free Software Foundation, either version 3 of the License,
11CC or (at your option) any later version.
12CC
13CC GNU Emacs is distributed in the hope that it will be useful, but
14CC WITHOUT ANY WARRANTY; without even the implied warranty of
15CC MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16CC General Public License for more details.
17CC
18CC You should have received a copy of the GNU General Public License
19CC along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
20
21 .section .text
22 .global _start
23_start:
24dnl movl $162, %eax CC SYS_nanosleep
25dnl leal timespec, %ebx
26dnl xorl %ecx, %ecx
27dnl int $0x80
28 leal 8(%esp), %ebp CC ebp = start of load area
29 subl $8, %esp CC (%esp) = primary fd, 4(%esp) = secondary fd
30 movl $-1, 4(%esp)
31.next_action:
32 movl (%ebp), %edx CC edx = action number
33 andl $-17, %edx
34 cmpl $0, %edx CC open file?
35 je .open_file
36 cmpl $3, %edx CC jump?
37 je .rest_of_exec
38 cmpl $4, %edx CC anonymous mmap?
39 je .do_mmap_anon
40.do_mmap:
41 subl $24, %esp
42 movl $90, %eax CC SYS_old_mmap
43 movl %esp, %ebx
44 movl 4(%ebp), %ecx CC address
45 movl %ecx, (%esp)
46 movl 16(%ebp), %ecx CC length
47 movl %ecx, 4(%esp)
48 movl 12(%ebp), %ecx CC protection
49 movl %ecx, 8(%esp)
50 movl 20(%ebp), %ecx CC flags
51 movl %ecx, 12(%esp)
52 testl $16, (%ebp) CC primary?
53 movl 28(%esp), %ecx
54 cmovzl 24(%esp), %ecx
55 movl %ecx, 16(%esp) CC fd
56 movl 8(%ebp), %ecx CC offset
57 movl %ecx, 20(%esp)
58.do_mmap_1:
59 int $0x80
60 addl $24, %esp CC restore esp
61 cmpl $-1, %eax CC mmap failed?
62 je .perror
63 movl 24(%ebp), %ecx CC clear
64 testl %ecx, %ecx
65 jz .continue
66 movl 4(%ebp), %esi CC start of mapping
67 addl 16(%ebp), %esi CC end of mapping
68 subl %ecx, %esi CC start of clear area
69.again:
70 testl %ecx, %ecx
71 jz .continue
72 subl $1, %ecx
73 movb $0, (%esi, %ecx, 1)
74 jmp .again
75.continue:
76 leal 28(%ebp), %ebp
77 jmp .next_action
78.do_mmap_anon:
79 subl $24, %esp
80 movl $90, %eax CC SYS_old_mmap
81 movl %esp, %ebx
82 movl 4(%ebp), %ecx CC address
83 movl %ecx, (%esp)
84 movl 16(%ebp), %ecx CC length
85 movl %ecx, 4(%esp)
86 movl 12(%ebp), %ecx CC protection
87 movl %ecx, 8(%esp)
88 movl 20(%ebp), %ecx CC flags
89 movl %ecx, 12(%esp)
90 movl $-1, 16(%esp) CC fd
91 movl 8(%ebp), %ecx CC offset
92 movl %ecx, 20(%esp)
93 jmp .do_mmap_1
94.open_file:
95 movl $5, %eax CC SYS_open
96 leal 4(%ebp), %ebx CC ebx = %esp + 8
97 pushl %ebx
98 xorl %ecx, %ecx CC flags = O_RDONLY
99 xorl %edx, %edx CC mode = 0
100 int $0x80
101 cmpl $-1, %eax CC open failed?
102 jle .perror
103 movl %ebp, %esi CC (esi) = original action number
104 popl %ebp CC ebp = start of string
105 movl %ebp, %ecx CC char past separator
106 decl %ebp
107.nextc:
108 incl %ebp
109 movb (%ebp), %dl CC dl = *ebp
110 cmpb $47, %dl CC dl == '\?'?
111 jne .nextc1
112 leal 1(%ebp), %ecx CC ecx = char past separator
113.nextc1:
114 cmpb $0, %dl CC dl == 0?
115 jne .nextc
116 addl $4, %ebp CC adjust past ebp prior to rounding
117 andl $-4, %ebp CC round ebp up to the next long
118 testl $16, (%esi) CC original action number & 16?
119 jz .primary
120 movl %eax, 4(%esp) CC secondary fd = eax
121 jmp .next_action
122.primary:
123 pushl %ebp
124 xorl %esi, %esi CC arg3
125 movl %eax, 4(%esp) CC primary fd = eax
126 xorl %edx, %edx CC arg2
127 movl $15, %ebx CC PR_SET_NAME, arg1 = ecx
128 xorl %edi, %edi CC arg4
129 movl $172, %eax CC SYS_prctl
130 xorl %ebp, %ebp CC arg5
131 int $0x80 CC syscall
132 popl %ebp
133 jmp .next_action
134.perror:
135 movl %eax, %ebx
136 negl %ebx
137 movl $1, %eax
138 int $0x80
139.rest_of_exec:
140 movl 8(%esp), %ecx CC ecx = original stack pointer
141 movl (%ecx), %esi CC esi = argc
142 leal 8(%ecx, %esi, 4), %ecx CC ecx = start of environ
143.skip_environ:
144 movl (%ecx), %esi CC envp[N]
145 addl $4, %ecx
146 testl %esi, %esi CC envp[n] ?
147 jnz .skip_environ CC otherwise, esi is now at the start of auxv
148.one_auxv:
149 movl (%ecx), %esi CC auxv type
150 leal 8(%ecx), %ecx CC skip to next auxv
151 testl %esi, %esi CC is 0?
152 jz .cleanup
153 cmpl $3, %esi CC is AT_PHDR
154 je .replace_phdr
155 cmpl $4, %esi CC is AT_PHENT?
156 je .replace_phent
157 cmpl $5, %esi CC is AT_PHNUM?
158 je .replace_phnum
159 cmpl $9, %esi CC is AT_ENTRY?
160 je .replace_entry
161 cmpl $7, %esi CC is AT_BASE
162 je .replace_base
163 jmp .one_auxv
164.replace_phdr:
165 movl 20(%ebp), %esi
166 movl %esi, -4(%ecx)
167 jmp .one_auxv
168.replace_phent:
169 movl 12(%ebp), %esi
170 movl %esi, -4(%ecx)
171 jmp .one_auxv
172.replace_phnum:
173 movl 16(%ebp), %esi
174 movl %esi, -4(%ecx)
175 jmp .one_auxv
176.replace_entry:
177 movl 8(%ebp), %esi
178 movl %esi, -4(%ecx)
179 jmp .one_auxv
180.replace_base:
181 movl 24(%ebp), %esi
182 movl %esi, -4(%ecx)
183 jmp .one_auxv
184.cleanup:
185 movl $6, %eax CC SYS_close
186 cmpl $-1, 4(%esp) CC see if interpreter fd is set
187 je .cleanup_1
188 movl 4(%esp), %ebx
189 int $0x80
190 movl $6, %eax CC SYS_close
191.cleanup_1:
192 movl (%esp), %ebx
193 int $0x80
194.enter:
195 pushl $0
196 popfl CC restore floating point state
197 movl 8(%esp), %esp CC restore initial stack pointer
198 xorl %edx, %edx CC clear rtld_fini
199 jmpl *4(%ebp) CC entry
200
201timespec:
202 .long 10
203 .long 10
diff --git a/exec/loader-x86_64.s b/exec/loader-x86_64.s
new file mode 100644
index 00000000000..acba609b202
--- /dev/null
+++ b/exec/loader-x86_64.s
@@ -0,0 +1,195 @@
1define(`CC', `
2dnl')
3
4CC Copyright (C) 2023 Free Software Foundation, Inc.
5CC
6CC This file is part of GNU Emacs.
7CC
8CC GNU Emacs is free software: you can redistribute it and/or modify
9CC it under the terms of the GNU General Public License as published
10CC by the Free Software Foundation, either version 3 of the License,
11CC or (at your option) any later version.
12CC
13CC GNU Emacs is distributed in the hope that it will be useful, but
14CC WITHOUT ANY WARRANTY; without even the implied warranty of
15CC MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16CC General Public License for more details.
17CC
18CC You should have received a copy of the GNU General Public License
19CC along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
20
21 .section .text
22 .global _start
23_start:
24dnl movq $35, %rax CC SYS_nanosleep
25dnl leaq timespec(%rip), %rdi
26dnl xorq %rsi, %rsi
27dnl syscall
28 popq %r13 CC original SP
29 popq %r15 CC size of load area.
30 movq $-1, %r12 CC r12 is the interpreter fd
31.next_action:
32 movq (%rsp), %r14 CC action number
33 movq %r14, %r15 CC original action number
34 andq $-17, %r14
35 cmpq $0, %r14 CC open file?
36 je .open_file
37 cmpq $3, %r14 CC jump?
38 je .rest_of_exec
39 cmpq $4, %r14 CC anonymous mmap?
40 je .do_mmap_anon
41.do_mmap:
42 movq $9, %rax CC SYS_mmap
43 movq 8(%rsp), %rdi CC address
44 movq 16(%rsp), %r9 CC offset
45 movq 24(%rsp), %rdx CC protection
46 movq 32(%rsp), %rsi CC length
47 movq 40(%rsp), %r10 CC flags
48 CC set r8 to the primary fd unless r15 & 16
49 testq $16, %r15
50 movq %r12, %r8
51 cmovzq %rbx, %r8
52.do_mmap_1:
53 syscall
54 cmpq $-1, %rax CC mmap failed
55 je .perror
56 movq 48(%rsp), %r9 CC clear
57 testq %r9, %r9
58 jz .continue
59 movq 8(%rsp), %r10 CC start of mapping
60 addq 32(%rsp), %r10 CC end of mapping
61 subq %r9, %r10 CC start of clear area
62.again:
63 testq %r9, %r9
64 jz .continue
65 subq $1, %r9
66 movb $0, (%r10, %r9, 1)
67 jmp .again
68.continue:
69 leaq 56(%rsp), %rsp
70 jmp .next_action
71.do_mmap_anon:
72 movq $9, %rax CC SYS_mmap
73 movq 8(%rsp), %rdi CC address
74 movq 16(%rsp), %r9 CC offset
75 movq 24(%rsp), %rdx CC protection
76 movq 32(%rsp), %rsi CC length
77 movq 40(%rsp), %r10 CC flags
78 movq $-1, %r8 CC -1
79 jmp .do_mmap_1
80.open_file:
81 movq $2, %rax CC SYS_open
82 leaq 8(%rsp), %rdi CC rdi = %rsp + 8
83 xorq %rsi, %rsi CC flags = O_RDONLY
84 xorq %rdx, %rdx CC mode = 0
85 syscall
86 cmpq $-1, %rax CC open failed
87 jle .perror
88 movq %rdi, %rsp CC rsp = start of string
89 subq $1, %rsp
90 movq %rsp, %r14 CC r14 = start of string
91.nextc:
92 addq $1, %rsp
93 movb (%rsp), %dil CC rdi = *rsp
94 cmpb $47, %dil CC *rsp == '/'?
95 jne .nextc1
96 movq %rsp, %r14 CC r14 = rsp
97 addq $1, %r14 CC r14 = char past separator
98.nextc1:
99 cmpb $0, %dil CC *rsp == 0?
100 jne .nextc
101 addq $8, %rsp CC adjust past rsp prior to rounding
102 andq $-8, %rsp CC round rsp up to the next quad
103 testq $16, %r15 CC r15 & 16?
104 jz .primary
105 movq %rax, %r12 CC otherwise, move fd to r12
106 jmp .next_action
107.primary:
108 movq %rax, %rbx CC if not, move fd to rbx
109 movq $157, %rax CC SYS_prctl
110 movq $15, %rdi CC PR_SET_NAME
111 movq %r14, %rsi CC arg1
112 xorq %rdx, %rdx CC arg2
113 xorq %r10, %r10 CC arg3
114 xorq %r8, %r8 CC arg4
115 xorq %r9, %r9 CC arg5
116 syscall
117 jmp .next_action
118.perror:
119 movq %rax, %r12 CC error code
120 negq %r12
121 movq $1, %rax CC SYS_write
122 movq $1, %rdi CC stdout
123 leaq error(%rip), %rsi CC buffer
124 movq $23, %rdx CC count
125 syscall
126 movq $60, %rax CC SYS_exit
127 movq %r12, %rdi CC code
128 syscall
129.rest_of_exec: CC rsp now points to six quads:
130 movq %rsp, %r8 CC now, they are r8
131 movq %r13, %rsp CC restore SP
132 popq %r10 CC argc
133 leaq 8(%rsp,%r10,8), %rsp CC now at start of environ
134.skip_environ:
135 popq %r10 CC envp[N]
136 testq %r10, %r10 CC envp[n]?
137 jnz .skip_environ CC otherwise, rsp is now at the start of auxv
138.one_auxv:
139 popq %rcx CC auxv type
140 addq $8, %rsp CC skip value
141 testq %rcx, %rcx CC is 0?
142 jz .cleanup
143 cmpq $3, %rcx CC is AT_PHDR?
144 je .replace_phdr
145 cmpq $4, %rcx CC is AT_PHENT?
146 je .replace_phent
147 cmpq $5, %rcx CC is AT_PHNUM?
148 je .replace_phnum
149 cmpq $9, %rcx CC is AT_ENTRY?
150 je .replace_entry
151 cmpq $7, %rcx CC is AT_BASE?
152 je .replace_base
153 jmp .one_auxv
154.replace_phdr:
155 movq 40(%r8), %r9
156 movq %r9, -8(%rsp) CC set at_phdr
157 jmp .one_auxv
158.replace_phent:
159 movq 24(%r8), %r9
160 movq %r9, -8(%rsp) CC set at_phent
161 jmp .one_auxv
162.replace_phnum:
163 movq 32(%r8), %r9
164 movq %r9, -8(%rsp) CC set at_phnum
165 jmp .one_auxv
166.replace_entry:
167 movq 16(%r8), %r9
168 movq %r9, -8(%rsp) CC set at_entry
169 jmp .one_auxv
170.replace_base:
171 movq 48(%r8), %r9
172 movq %r9, -8(%rsp) CC set at_base
173 jmp .one_auxv
174.cleanup:
175 movq $3, %rax CC SYS_close
176 cmpq $-1, %r12 CC see if interpreter fd is set
177 je .cleanup_1
178 movq %r12, %rdi
179 syscall
180 movq $3, %rax CC SYS_close
181.cleanup_1:
182 movq %rbx, %rdi
183 syscall
184.enter:
185 pushq $0
186 popfq CC clear FP state
187 movq %r13, %rsp CC restore SP
188 xorq %rdx, %rdx CC clear rtld_fini
189 jmpq *8(%r8) CC entry
190
191error:
192 .ascii "_start: internal error."
193timespec:
194 .quad 10
195 .quad 10
diff --git a/exec/mipsel-user.h b/exec/mipsel-user.h
new file mode 100644
index 00000000000..dc3f98eb4e7
--- /dev/null
+++ b/exec/mipsel-user.h
@@ -0,0 +1,43 @@
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
21
22#ifndef _MIPSEL_USER_H_
23#define _MIPSEL_USER_H_
24
25#include <sys/user.h>
26
27#ifndef ELF_NGREG
28#define ELF_NGREG 45
29#endif /* ELF_NGREG */
30
31
32
33/* This file defines a structure containing user mode general purpose
34 registers on 32-bit mipsel systems. */
35
36struct mipsel_regs
37{
38 /* General purpose registers. */
39 uint64_t gregs[ELF_NGREG];
40};
41
42#endif /* _MIPSEL_USER_H_ */
43
diff --git a/exec/mipsfpu.c b/exec/mipsfpu.c
new file mode 100644
index 00000000000..f5fa5720804
--- /dev/null
+++ b/exec/mipsfpu.c
@@ -0,0 +1,289 @@
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#include <errno.h>
22
23#include "mipsfpu.h"
24
25
26
27/* OABI MIPS systems support several different modes of execution.
28 Each mode differs in the size and utilization of the hardware
29 floating-point registers.
30
31 Linux normally sets the floating point mode to one appropriate for
32 execution, taking into account the floating point modes of the
33 interpreter and executable binaries. However, this logic is
34 forsaken when the `execve' system call is overwritten.
35
36 Thus, the correct floating point mode must be determined and set
37 within the loader binary. */
38
39
40
41/* Various constants used throughout this code. */
42
43#define MIPS_ABI_FP_ANY 0 /* FP ABI doesn't matter */
44#define MIPS_ABI_FP_DOUBLE 1 /* -mdouble-float */
45#define MIPS_ABI_FP_SINGLE 2 /* -msingle-float */
46#define MIPS_ABI_FP_SOFT 3 /* -msoft-float */
47#define MIPS_ABI_FP_OLD_64 4 /* -mips32r2 -mfp64 */
48#define MIPS_ABI_FP_XX 5 /* -mfpxx */
49#define MIPS_ABI_FP_64 6 /* -mips32r2 -mfp64 */
50#define MIPS_ABI_FP_64A 7 /* -mips32r2 -mfp64 -mno-odd-spreg */
51
52#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used. */
53#define EF_MIPS_PIC 2 /* Contains PIC code. */
54#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence. */
55#define EF_MIPS_XGOT 8
56#define EF_MIPS_64BIT_WHIRL 16
57#define EF_MIPS_ABI2 32
58#define EF_MIPS_ABI_ON32 64
59#define EF_MIPS_FP64 512 /* Uses FP64 (12 callee-saved). */
60#define EF_MIPS_NAN2008 1024 /* Uses IEEE 754-2008 NaN encoding. */
61#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level. */
62
63
64
65/* Structure describing the requirements of a single floating-point
66 ABI. */
67
68struct mode_description
69{
70 /* Whether or not the ABI only executes single precision
71 instructions, and can operate in both 32-bit or 64-bit floating
72 point mode. */
73 bool single;
74
75 /* Whether or not the ABI performs floating point operations in
76 software, using integer registers. */
77 bool soft;
78
79 /* Whether or not the ABI requires the use of 64-bit floating point
80 registers. */
81 bool fr1;
82
83 /* Whether or not the ABI requires the use of 64-bit floating point
84 registers on NABI systems, and 32-bit ones on OABI systems. */
85 bool frdefault;
86
87 /* Whether or not this ABI requires single precision floating point
88 emulation. */
89 bool fre;
90};
91
92static struct mode_description fpu_reqs[] =
93 {
94 [MIPS_ABI_FP_ANY] = { true, true, true, true, true, },
95 [MIPS_ABI_FP_DOUBLE] = { false, false, false, true, true, },
96 [MIPS_ABI_FP_SINGLE] = { true, false, false, false, false, },
97 [MIPS_ABI_FP_SOFT] = { false, true, false, false, false, },
98 [MIPS_ABI_FP_OLD_64] = { false, false, false, false, false, },
99 [MIPS_ABI_FP_XX] = { false, false, true, true, true, },
100 [MIPS_ABI_FP_64] = { false, false, true, false, false, },
101 [MIPS_ABI_FP_64A] = { false, false, true, false, true, },
102 };
103
104
105
106/* Return whether or not the given floating-point ABI is valid. */
107
108static bool
109valid_abi_p (int abi)
110{
111 switch (abi)
112 {
113 case MIPS_ABI_FP_ANY:
114 case MIPS_ABI_FP_DOUBLE:
115 case MIPS_ABI_FP_SINGLE:
116 case MIPS_ABI_FP_SOFT:
117 case MIPS_ABI_FP_OLD_64:
118 case MIPS_ABI_FP_XX:
119 case MIPS_ABI_FP_64:
120 case MIPS_ABI_FP_64A:
121 return true;
122
123 default:
124 return false;
125 }
126}
127
128/* Return the floating point mode appropriate for the specified
129 floating point ABI. */
130
131static int
132fp_mode_for_abi (int abi)
133{
134 struct mode_description *desc;
135
136 desc = &fpu_reqs[abi];
137
138 if (desc->fre)
139 return FP_FRE;
140 else if (desc->fr1)
141 return FP_FR1;
142
143 return FP_FR0;
144}
145
146/* Determine whether or not the CPU is capable of operating in FR0
147 floating point mode. */
148
149bool
150cpu_supports_fr0_p (void)
151{
152#if defined __mips_isa_rev && __mips_isa_rev >= 6
153 return true;
154#else /* !defined __mips_isa_rev | mips_isa_rev < 6 */
155 return false;
156#endif /* defined __mips_isa_rev && mips_isa_rev >= 6 */
157}
158
159/* Determine the FPU mode for the executable whose ELF header is
160 HEADER. If INTERPRETER is non-NULL, also take an interpreter whose
161 header is INTERPRETER into account.
162
163 ABIFLAGS should be HEADER's corresponding PT_MIPS_ABIFLAGS program
164 header, and ABIFLAGS1 should be that of INTERPRETER, if set. Both
165 fields may be NULL if no PT_MIPS_ABIFLAGS header is present; in
166 that case, use HEADER->e_flags to determine the ABI instead.
167
168 Return the FPU mode in *MODE. Value is 0 upon success, 1
169 otherwise, with errno set. */
170
171int
172determine_fpu_mode (elf_header *header, elf_header *interpreter,
173 int *mode, struct mips_elf_abi_flags *abiflags,
174 struct mips_elf_abi_flags *abiflags1)
175{
176 int exec_abi, interpreter_abi;
177 struct mode_description *exec_desc, *interpreter_desc, common;
178
179 /* Figure out the executable's floating point ABI. First, consult
180 header->e_flags, and use the old 64-bit floating point ABI if it
181 is specified. */
182
183 exec_abi = MIPS_ABI_FP_ANY;
184
185 /* First, check HEADER->e_flags. */
186
187 if (header->e_flags & EF_MIPS_FP64)
188 exec_abi = MIPS_ABI_FP_OLD_64;
189
190 /* Next, use ABIFLAGS if it exists. */
191
192 if (abiflags && valid_abi_p (abiflags->fp_abi))
193 exec_abi = abiflags->fp_abi;
194 else if (abiflags)
195 {
196 errno = ENOEXEC;
197 return 1;
198 }
199
200 /* Now determine that of the interpreter. */
201
202 interpreter_abi = MIPS_ABI_FP_ANY;
203
204 if (interpreter)
205 {
206 if (interpreter->e_flags & EF_MIPS_FP64)
207 interpreter_abi = MIPS_ABI_FP_OLD_64;
208
209 if (abiflags1 && valid_abi_p (abiflags->fp_abi))
210 interpreter_abi = abiflags->fp_abi;
211 else if (abiflags1)
212 {
213 errno = ELIBBAD;
214 return 1;
215 }
216 }
217
218 /* If no interpreter flag is set, just return that of the
219 executable. */
220
221 if (!interpreter)
222 {
223 *mode = fp_mode_for_abi (exec_abi);
224 return 0;
225 }
226
227 /* Otherwise, compare both ABIs and try to find one which will run
228 both kinds of code.
229
230 First, see if there's an easy way out: both ABIs are identical,
231 or one ABI is MIPS_ABI_FP_ANY. */
232
233 if (exec_abi == interpreter_abi)
234 {
235 *mode = fp_mode_for_abi (exec_abi);
236 return 0;
237 }
238 else if (exec_abi == MIPS_ABI_FP_ANY)
239 {
240 *mode = fp_mode_for_abi (interpreter_abi);
241 return 0;
242 }
243 else if (interpreter_abi == MIPS_ABI_FP_ANY)
244 {
245 *mode = fp_mode_for_abi (exec_abi);
246 return 0;
247 }
248
249 /* If that doesn't work, compare various characteristics of both
250 ABIs and select an appropriate floating point mode. */
251
252 exec_desc = &fpu_reqs[exec_abi];
253 interpreter_desc = &fpu_reqs[interpreter_abi];
254
255 /* Merge both sets of requirements. */
256 common.single = exec_desc->single && interpreter_desc->single;
257 common.soft = exec_desc->soft && interpreter_desc->soft;
258 common.fr1 = exec_desc->fr1 && interpreter_desc->fr1;
259 common.frdefault = exec_desc->frdefault && interpreter_desc->frdefault;
260 common.fre = exec_desc->fre && interpreter_desc->fre;
261
262 /* Default to a mode capable of running code expecting 32-bit
263 registers. */
264
265 if (!(header->e_flags & EF_MIPS_ABI2))
266 *mode = FP_FR0;
267 else
268 /* But in this case, use FR1. */
269 *mode = FP_FR1;
270
271 if (common.fre && !common.frdefault && !common.fr1)
272 /* Floating point emulation mode is required. */
273 *mode = FP_FRE;
274 else if ((common.fr1 && common.frdefault)
275 || (common.single && !common.frdefault)
276 || common.fr1)
277 /* 64-bit mode is required. */
278 *mode = FP_FR1;
279 else if (!common.fre && !common.frdefault
280 && !common.fr1 && !common.single
281 && !common.soft)
282 {
283 /* The floating point modes specified are incompatible. */
284 errno = ELIBBAD;
285 return -1;
286 }
287
288 return 0;
289}
diff --git a/exec/mipsfpu.h b/exec/mipsfpu.h
new file mode 100644
index 00000000000..2315db59e93
--- /dev/null
+++ b/exec/mipsfpu.h
@@ -0,0 +1,82 @@
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
21
22#ifndef _MIPSFPU_H_
23#define _MIPSFPU_H_
24
25#include "exec.h"
26
27struct mips_elf_abi_flags
28{
29 /* Version of flags structure. */
30 uint16_t version;
31
32 /* The level of the ISA: 1-5, 32, 64. */
33 uint8_t isa_level;
34
35 /* The revision of ISA: 0 for MIPS V and below, 1-n otherwise. */
36 uint8_t isa_rev;
37
38 /* The size of general purpose registers. */
39 uint8_t gpr_size;
40
41 /* The size of co-processor 1 registers. */
42 uint8_t cpr1_size;
43
44 /* The size of co-processor 2 registers. */
45 uint8_t cpr2_size;
46
47 /* The floating-point ABI. */
48 uint8_t fp_abi;
49
50 /* Mask of processor-specific extensions. */
51 uint32_t isa_ext;
52
53 /* Mask of ASEs used. */
54 uint32_t ases;
55
56 /* Mask of general flags. */
57 uint32_t flags1;
58
59 /* Mask of general flags. */
60 uint32_t flags2;
61};
62
63
64
65/* Floating point modes. */
66
67#define FP_FR0 0
68#define FP_FR1 1
69#define FP_FRE 3
70
71
72
73/* Defined in mipsfpu.c. */
74
75extern bool cpu_supports_fr0_p (void);
76extern int determine_fpu_mode (elf_header *, elf_header *,
77 int *, struct mips_elf_abi_flags *,
78 struct mips_elf_abi_flags *);
79
80
81
82#endif /* _MIPSFPU_H_ */
diff --git a/exec/test.c b/exec/test.c
new file mode 100644
index 00000000000..fa2a848837c
--- /dev/null
+++ b/exec/test.c
@@ -0,0 +1,105 @@
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 <signal.h>
23#include <stdio.h>
24#include <unistd.h>
25#include <stdlib.h>
26#include <errno.h>
27#include <string.h>
28
29#include <sys/wait.h>
30
31#include "exec.h"
32
33
34
35static void
36print_usage (void)
37{
38 fprintf (stderr, "test loader-name program [args...]\n"
39 "Run the given program using the specified loader.\n");
40}
41
42
43
44extern char **environ;
45
46/* This program uses libexec to wrap the execution of a child
47 process. */
48
49int
50main (int argc, char **argv)
51{
52 pid_t pid, child;
53 int sig;
54 sigset_t sigset;
55
56 /* Check that there are a sufficient number of arguments. */
57
58 if (argc < 3)
59 {
60 print_usage ();
61 return 1;
62 }
63
64 exec_init (argv[1]);
65
66 /* Block SIGCHLD to avoid reentrant modification of the child
67 process list. */
68
69 sigemptyset (&sigset);
70 sigaddset (&sigset, SIGCHLD);
71 sigprocmask (SIG_BLOCK, &sigset, NULL);
72
73 if (!(pid = fork ()))
74 {
75 tracing_execve (argv[2], argv + 2, environ);
76 fprintf (stderr, "tracing_execve: %s\n",
77 strerror (errno));
78 exit (1);
79 }
80 else if (after_fork (pid))
81 {
82 fprintf (stderr, "after_fork: %s\n",
83 strerror (errno));
84 exit (1);
85 }
86
87 /* Now start waiting for child processes to exit. */
88
89 while (true)
90 {
91 child = exec_waitpid (-1, &sig, 0);
92
93 /* If pid is -1, a system call has been handled. */
94
95 if (child == -1)
96 continue;
97
98 /* If the main process exits, then exit as well. */
99
100 if (child == pid && !WIFSTOPPED (sig))
101 return (WIFEXITED (sig)
102 ? WEXITSTATUS (sig)
103 : WTERMSIG (sig));
104 }
105}
diff --git a/exec/trace.c b/exec/trace.c
new file mode 100644
index 00000000000..3b384792d0a
--- /dev/null
+++ b/exec/trace.c
@@ -0,0 +1,1432 @@
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 <sys/ptrace.h>
23#include <sys/types.h>
24#include <sys/wait.h>
25
26#include <limits.h>
27#include <stddef.h>
28#include <string.h>
29#include <assert.h>
30#include <signal.h>
31#include <unistd.h>
32#include <stdlib.h>
33#include <errno.h>
34
35#include "exec.h"
36
37#include SYSCALL_HEADER
38#include USER_HEADER
39
40#ifdef __aarch64__
41#include <sys/uio.h> /* for struct iovec */
42#include <linux/elf.h> /* for NT_* */
43#endif /* __aarch64__ */
44
45#ifdef HAVE_SYS_UIO_H
46#include <sys/uio.h> /* for process_vm_readv */
47#endif /* HAVE_SYS_UIO_H */
48
49#ifndef SYS_SECCOMP
50#define SYS_SECCOMP 1
51#endif /* SYS_SECCOMP */
52
53#ifndef PTRACE_GETEVENTMSG
54#define PTRACE_GETEVENTMSG 0x4201
55#endif /* PTRACE_GETEVENTMSG */
56
57
58
59/* Program tracing functions.
60
61 The main entry point is the function `tracing_execve', which traces
62 the thread and calls exec. Each time that thread calls `clone',
63 the new child is traced as well.
64
65 Instead of calling `waitpid', call `exec_waitpid' instead. */
66
67
68
69/* Number of tracees children are allowed to create. */
70#define MAX_TRACEES 4096
71
72#ifdef __aarch64__
73
74/* Place PID's registers into *REGS. Return 1 upon failure, else
75 0. */
76
77int
78aarch64_get_regs (pid_t pid, USER_REGS_STRUCT *regs)
79{
80 struct iovec iov;
81
82 iov.iov_base = regs;
83 iov.iov_len = sizeof *regs;
84
85 return (ptrace (PTRACE_GETREGSET, pid, NT_PRSTATUS,
86 &iov) != 0);
87}
88
89/* Set PID's registers to *REGS. If SYSCALL_P, also update the
90 current system call number to the `x8' register.
91
92 Value is 1 upon failure, else 0. */
93
94int
95aarch64_set_regs (pid_t pid, USER_REGS_STRUCT *regs,
96 bool syscall_p)
97{
98 struct iovec iov;
99 USER_WORD callno;
100 long rc;
101
102 /* Write the user registers. */
103
104 iov.iov_base = regs;
105 iov.iov_len = sizeof *regs;
106
107 rc = ptrace (PTRACE_SETREGSET, pid, NT_PRSTATUS,
108 &iov);
109 if (rc < 0)
110 return 1;
111
112 /* Now, write the system call number if necessary. */
113
114 if (syscall_p)
115 {
116 callno = regs->regs[8];
117 iov.iov_base = &callno;
118 iov.iov_len = sizeof callno;
119
120 return (ptrace (PTRACE_SETREGSET, pid, NT_ARM_SYSTEM_CALL,
121 &iov) != 0);
122 }
123
124 return 0;
125}
126
127#endif /* __aarch64__ */
128
129
130
131/* List of all processes which are being traced. */
132static struct exec_tracee *tracing_processes;
133
134
135
136/* Read N bytes from TRACEE's memory, starting at the specified user
137 ADDRESS. Return its contents in BUFFER.
138
139 If there are unreadable pages within ADDRESS + N, the contents of
140 BUFFER after the first such page becomes undefined. */
141
142static void
143read_memory (struct exec_tracee *tracee, char *buffer,
144 USER_WORD n, USER_WORD address)
145{
146 USER_WORD word, n_words, n_bytes, i;
147 long rc;
148#ifdef HAVE_PROCESS_VM
149 struct iovec iov, remote;
150
151 /* If `process_vm_readv' is available, use it instead. */
152
153 iov.iov_base = buffer;
154 iov.iov_len = n;
155 remote.iov_base = (void *) address;
156 remote.iov_len = n;
157
158 /* Return immediately if successful. As long as some bytes were
159 read, consider the read to have been a success. */
160
161 if (n <= SSIZE_MAX
162 && ((size_t) process_vm_readv (tracee->pid, &iov, 1,
163 &remote, 1, 0) != -1))
164 return;
165
166#endif /* HAVE_PROCESS_VM */
167
168 /* First, read entire words from the tracee. */
169 n_words = n & ~(sizeof (USER_WORD) - 1);
170
171 /* Next, determine the number of bytes to read from the last
172 word. */
173 n_bytes = n & (sizeof (USER_WORD) - 1);
174
175 /* Start reading words. */
176 i = 0;
177 while (n_words)
178 {
179 rc = ptrace (PTRACE_PEEKTEXT, tracee->pid,
180 (void *) address + i, NULL);
181 word = rc;
182 memcpy (buffer, &word, sizeof word);
183 buffer += sizeof word;
184 i += sizeof word;
185 n_words -= sizeof word;
186 }
187
188 /* Now, read the remaining bytes. */
189 assert (n_bytes < sizeof (word));
190
191 if (n_bytes)
192 {
193 rc = ptrace (PTRACE_PEEKTEXT, tracee->pid,
194 (void *) address + i, NULL);
195 word = rc;
196
197 /* Copy only n_bytes to the caller. */
198 memcpy (buffer, &word, n_bytes);
199 }
200}
201
202/* Allocate N bytes of memory from TRACEE's stack. Return the address
203 of that memory upon success, else 0.
204
205 Place the updated user-mode registers of TRACEE in *NEW_REGS, which
206 should initially contain the current stack pointer of TRACEE.
207
208 REGS should contain the user mode registers of TRACEE prior to the
209 system call starting; it is not updated to reflect any changes. */
210
211USER_WORD
212user_alloca (struct exec_tracee *tracee, USER_REGS_STRUCT *regs,
213 USER_REGS_STRUCT *new_regs, USER_WORD n)
214{
215 USER_WORD sp, old_sp;
216
217 /* Get the current stack pointer. */
218 old_sp = sp = new_regs->STACK_POINTER;
219
220#if RED_ZONE_SIZE
221 /* Some ABI rules specify a ``red zone'' around the stack pointer
222 that is reserved for compiler optimizations. */
223
224#ifdef STACK_GROWS_DOWNWARDS
225 if (sp == regs->STACK_POINTER)
226 sp -= RED_ZONE_SIZE;
227#else /* !STACK_GROWS_DOWNWARDS */
228 if (sp == regs->STACK_POINTER)
229 sp += RED_ZONE_SIZE;
230#endif /* STACK_GROWS_DOWNWARDS */
231#endif /* RED_ZONE_SIZE */
232
233 /* Now take N off the stack. */
234
235#ifdef STACK_GROWS_DOWNWARDS
236 sp = sp - n;
237
238 /* Check for overflow. */
239
240 if (sp > new_regs->STACK_POINTER)
241 return 0;
242#else /* !STACK_GROWS_DOWNWARDS */
243 sp = sp + n;
244
245 /* Check for overflow. */
246
247 if (sp < new_regs->STACK_POINTER)
248 return 0;
249#endif /* STACK_GROWS_DOWNWARDS */
250
251 /* Set the stack pointer. */
252 new_regs->STACK_POINTER = sp;
253
254#ifdef __aarch64__
255 if (aarch64_set_regs (tracee->pid, new_regs, false))
256 goto fail;
257#else /* !__aarch64__ */
258 if (ptrace (PTRACE_SETREGS, tracee->pid, NULL,
259 new_regs))
260 goto fail;
261#endif /* __aarch64__ */
262
263 /* Now return the start of the new area. */
264#ifdef STACK_GROWS_DOWNWARDS
265 return sp;
266#else /* !STACK_GROWS_DOWNWARDS */
267 return sp - n;
268#endif /* STACK_GROWS_DOWNWARDS */
269
270 fail:
271 /* Restore the old stack pointer. */
272 new_regs->STACK_POINTER = old_sp;
273 return 0;
274}
275
276/* Copy N bytes to ADDRESS in TRACEE's address space from BUFFER.
277 Value is 0 upon success, else 1. */
278
279int
280user_copy (struct exec_tracee *tracee, const unsigned char *buffer,
281 USER_WORD address, USER_WORD n)
282{
283 USER_WORD start, end, word;
284 unsigned char *bytes;
285#ifdef HAVE_PROCESS_VM
286 struct iovec iov, remote;
287
288 /* Try to use `process_vm_writev' if possible, but fall back to
289 ptrace if something bad happens. */
290
291 iov.iov_base = (void *) buffer;
292 iov.iov_len = n;
293 remote.iov_base = (void *) address;
294 remote.iov_len = n;
295
296 if (n <= SSIZE_MAX
297 && ((size_t) process_vm_writev (tracee->pid, &iov, 1,
298 &remote, 1, 0) == n))
299 return 0;
300#endif /* HAVE_PROCESS_VM */
301
302 /* Calculate the start and end positions for the write. */
303
304 start = address;
305 end = address + n;
306
307 /* Write from start to the last word. */
308
309 while (start < end)
310 {
311 if (start + sizeof word <= end)
312 {
313 /* Write a word by itself and increment start. */
314 memcpy (&word, buffer, sizeof word);
315 buffer += sizeof word;
316
317 if (ptrace (PTRACE_POKEDATA, tracee->pid,
318 (void *) start, (void *) word))
319 return 1;
320
321 start += sizeof word;
322 }
323 else
324 {
325 /* Only end - start bytes should be written.
326 Read the word at start from tracee->pid, then write
327 it back with changes. */
328
329 word = ptrace (PTRACE_PEEKDATA, tracee->pid,
330 (void *) start, NULL);
331 bytes = (unsigned char *) &word;
332 memcpy (bytes, buffer, end - start);
333
334 if (ptrace (PTRACE_POKEDATA, tracee->pid,
335 (void *) start, (void *) word))
336 return 1;
337
338 /* Writing was successful. */
339 return 0;
340 }
341 }
342
343 return 0;
344}
345
346
347
348/* Chain of free exec_tracee structures. */
349static struct exec_tracee *free_tracees;
350
351/* Remove the specified TRACEE from the chain of all processes being
352 traced. */
353
354static void
355remove_tracee (struct exec_tracee *tracee)
356{
357 struct exec_tracee **last;
358
359 last = &tracing_processes;
360 while (*last)
361 {
362 if (*last == tracee)
363 {
364 *last = tracee->next;
365
366 /* Link the tracee onto the list of free tracees. */
367 tracee->next = free_tracees;
368
369#ifndef REENTRANT
370 /* Free the exec file, if any. */
371 free (tracee->exec_file);
372 tracee->exec_file = NULL;
373#endif /* REENTRANT */
374
375 free_tracees = tracee;
376
377 return;
378 }
379 else
380 last = &(*last)->next;
381 }
382}
383
384
385
386/* Child process tracing. */
387
388/* Array of `struct exec_tracees' that they are allocated from. */
389static struct exec_tracee static_tracees[MAX_TRACEES];
390
391/* Number of tracees currently allocated. */
392static int tracees;
393
394/* Return the `struct exec_tracee' corresponding to the specified
395 PROCESS. */
396
397static struct exec_tracee *
398find_tracee (pid_t process)
399{
400 struct exec_tracee *tracee;
401
402 for (tracee = tracing_processes; tracee; tracee = tracee->next)
403 {
404 if (tracee->pid == process)
405 return tracee;
406 }
407
408 return NULL;
409}
410
411/* Prepare to handle the completion of a `clone' system call.
412
413 If the new clone is not yet being traced, create a new tracee for
414 PARENT's child, copying over its current command line. Then, set
415 `new_child' in the new tracee. Otherwise, continue it until the
416 next syscall. */
417
418static void
419handle_clone_prepare (struct exec_tracee *parent)
420{
421#ifndef REENTRANT
422 long rc;
423 unsigned long pid;
424 struct exec_tracee *tracee;
425
426 rc = ptrace (PTRACE_GETEVENTMSG, parent->pid, NULL,
427 &pid);
428 if (rc)
429 return;
430
431 /* See if the tracee already exists. */
432 tracee = find_tracee (pid);
433
434 if (tracee)
435 {
436 /* Continue the tracee. Record its command line, as that has
437 not yet been done. */
438
439 assert (tracee->new_child);
440 tracee->new_child = false;
441 tracee->exec_file = NULL;
442 ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0);
443
444 if (parent->exec_file)
445 tracee->exec_file = strdup (parent->exec_file);
446 return;
447 }
448
449 if (free_tracees)
450 {
451 tracee = free_tracees;
452 free_tracees = free_tracees->next;
453 }
454 else if (tracees < MAX_TRACEES)
455 {
456 tracee = &static_tracees[tracees];
457 tracees++;
458 }
459#ifndef REENTRANT
460 /* Try to allocate a tracee using `malloc' if this library is
461 not being built to run inside a signal handler. */
462 else if ((tracee = malloc (sizeof *tracee)))
463 ;
464#endif /* REENTRANT */
465 else
466 return;
467
468 tracee->pid = pid;
469 tracee->next = tracing_processes;
470 tracee->waiting_for_syscall = false;
471 tracee->new_child = true;
472 tracee->exec_file = NULL;
473 tracing_processes = tracee;
474
475 /* Copy over the command line. */
476
477 if (parent->exec_file)
478 tracee->exec_file = strdup (parent->exec_file);
479#endif /* REENTRANT */
480}
481
482/* Handle the completion of a `clone' or `clone3' system call,
483 resulting in the creation of the process PID. If TRACEE is NULL,
484 allocate a new tracee structure from a static area for the
485 processes's pid, then set TRACEE->new_child to true and await the
486 parent's corresponding ptrace event to arrive; otherwise, just
487 clear TRACEE->new_child.
488
489 Value is 0 upon success, 2 if TRACEE should remain suspended until
490 the parent's ptrace-stop, and 1 otherwise. */
491
492static int
493handle_clone (struct exec_tracee *tracee, pid_t pid)
494{
495 long rc;
496 int flags, value;
497
498 /* Now allocate a new tracee, either from static_tracees or the free
499 list, if no tracee was supplied. */
500
501 value = 0;
502
503 if (!tracee)
504 {
505 if (free_tracees)
506 {
507 tracee = free_tracees;
508 free_tracees = free_tracees->next;
509 }
510 else if (tracees < MAX_TRACEES)
511 {
512 tracee = &static_tracees[tracees];
513 tracees++;
514 }
515#ifndef REENTRANT
516 /* Try to allocate a tracee using `malloc' if this library is
517 not being built to run inside a signal handler. */
518 else if ((tracee = malloc (sizeof *tracee)))
519 ;
520#endif /* REENTRANT */
521 else
522 return 1;
523
524 tracee->pid = pid;
525 tracee->next = tracing_processes;
526 tracee->waiting_for_syscall = false;
527#ifndef REENTRANT
528 tracee->exec_file = NULL;
529#endif /* REENTRANT */
530 tracing_processes = tracee;
531 tracee->new_child = true;
532
533 /* Wait for the ptrace-stop to happen in the parent. */
534 value = 2;
535 }
536 else
537 /* Clear the flag saying that this is a newly created child
538 process. */
539 tracee->new_child = false;
540
541 /* Apply required options to the child, so that the kernel
542 automatically traces children and makes it easy to differentiate
543 between system call traps and other kinds of traps. */
544
545 flags = PTRACE_O_TRACECLONE;
546 flags |= PTRACE_O_TRACEVFORK;
547 flags |= PTRACE_O_TRACEFORK;
548 flags |= PTRACE_O_TRACESYSGOOD;
549 flags |= PTRACE_O_TRACEEXIT;
550
551 rc = ptrace (PTRACE_SETOPTIONS, pid, 0, flags);
552
553 if (rc)
554 goto bail;
555
556 if (value != 2)
557 {
558 /* The new tracee is currently stopped. Continue it until the next
559 system call. */
560
561 rc = ptrace (PTRACE_SYSCALL, pid, 0, 0);
562
563 if (rc)
564 goto bail;
565 }
566
567 return value;
568
569 bail:
570 remove_tracee (tracee);
571 return 1;
572}
573
574
575
576/* NOTICE: none of these functions should ever call `malloc' or
577 another async signal unsafe function. */
578
579/* File name of the loader binary. */
580static const char *loader_name;
581
582
583
584/* Return whether or not the trap signal described by SIGNAL is
585 generated by a system call being attempted by a tracee. */
586
587static bool
588syscall_trap_p (siginfo_t *signal)
589{
590 /* SIGTRAP delivered by the kernel means this is a system call
591 stop. */
592 return (signal->si_code == SIGTRAP
593 || signal->si_code == (SIGTRAP | SI_KERNEL));
594}
595
596/* Check if the wait status STATUS indicates a system call trap.
597 TRACEE is the process whose stop STATUS describes. If TRACEE exits
598 while this information is being determined, return -1; if STATUS
599 indicates some other kind of stop, return 1 after continuing
600 TRACEE. Value is 0 otherwise. */
601
602static int
603check_signal (struct exec_tracee *tracee, int status)
604{
605 siginfo_t siginfo;
606
607 switch ((status & 0xfff00) >> 8)
608 {
609 case SIGTRAP:
610 /* Now, use PTRACE_GETSIGINFO to determine whether or not the
611 signal was delivered in response to a system call. */
612
613 if (ptrace (PTRACE_GETSIGINFO, tracee->pid, 0, &siginfo))
614 return -1;
615
616 if (!syscall_trap_p (&siginfo))
617 {
618 if (siginfo.si_code < 0)
619 /* SIGTRAP delivered from userspace. Pass it on. */
620 ptrace (PTRACE_SYSCALL, tracee->pid, 0, SIGTRAP);
621 else
622 ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0);
623
624 return 1;
625 }
626
627 case SIGTRAP | 0x80: /* SIGTRAP | 0x80 specifically refers to
628 system call traps. */
629 break;
630
631#ifdef SIGSYS
632 case SIGSYS:
633 if (ptrace (PTRACE_GETSIGINFO, tracee->pid, 0, &siginfo))
634 return -1;
635
636 /* Continue the process until the next syscall, but don't
637 pass through the signal if an emulated syscall led to
638 it. */
639#ifdef HAVE_SIGINFO_T_SI_SYSCALL
640#ifndef __arm__
641 ptrace (PTRACE_SYSCALL, tracee->pid,
642 0, ((siginfo.si_code == SYS_SECCOMP
643 && siginfo.si_syscall == -1)
644 ? 0 : status));
645#else /* __arm__ */
646 ptrace (PTRACE_SYSCALL, tracee->pid,
647 0, ((siginfo.si_code == SYS_SECCOMP
648 && siginfo.si_syscall == 222)
649 ? 0 : status));
650#endif /* !__arm__ */
651#else /* !HAVE_SIGINFO_T_SI_SYSCALL */
652 /* Drop this signal, since what caused it is unknown. */
653 ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0);
654#endif /* HAVE_SIGINFO_T_SI_SYSCALL */
655 return 1;
656#endif /* SIGSYS */
657
658 default:
659 /* Continue the process until the next syscall. */
660 ptrace (PTRACE_SYSCALL, tracee->pid, 0, status);
661 return 1;
662 }
663
664 return 0;
665}
666
667
668
669/* Handle an `exec' system call from the given TRACEE. REGS are the
670 tracee's current user-mode registers.
671
672 Rewrite the system call arguments to use the loader binary. Then,
673 continue the system call until the loader is loaded. Write the
674 information necessary to load the original executable into the
675 loader's stack.
676
677 Value is 0 upon success, 1 upon a generic failure before the loader
678 is loaded, 2 if the process has stopped, and 3 if something failed,
679 but it is too late to handle it.
680
681 Set errno appropriately upon returning a generic failure. */
682
683static int
684handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs)
685{
686 char buffer[PATH_MAX + 80], *area;
687 USER_REGS_STRUCT original;
688 size_t size, loader_size;
689 USER_WORD loader, size1, sp;
690 int rc, wstatus;
691 siginfo_t siginfo;
692
693 /* Save the old stack pointer. */
694 sp = regs->STACK_POINTER;
695
696 /* Read the file name. */
697 read_memory (tracee, buffer, PATH_MAX,
698 regs->SYSCALL_ARG_REG);
699
700 /* Make sure BUFFER is NULL terminated. */
701
702 if (!memchr (buffer, '\0', PATH_MAX))
703 {
704 errno = ENAMETOOLONG;
705 return 1;
706 }
707
708 /* Copy over the registers as they originally were. */
709 memcpy (&original, regs, sizeof *regs);
710
711 /* Figure out what the loader needs to do. */
712 again1:
713 area = exec_0 (buffer, tracee, &size, regs);
714
715 if (!area)
716 {
717 /* Handle SIGINTR errors caused by IO. */
718 if (errno == EINTR)
719 goto again1;
720
721 return 1;
722 }
723
724 /* Rewrite the first argument to point to the loader. */
725
726 loader_size = strlen (loader_name) + 1;
727 loader = user_alloca (tracee, &original, regs,
728 loader_size);
729
730 if (!loader)
731 {
732 errno = ENOMEM;
733 return 1;
734 }
735
736 if (user_copy (tracee, (unsigned char *) loader_name,
737 loader, loader_size))
738 {
739 errno = EIO;
740 return 1;
741 }
742
743 regs->SYSCALL_ARG_REG = loader;
744
745#ifdef __aarch64__
746
747 if (aarch64_set_regs (tracee->pid, regs, false))
748 {
749 errno = EIO;
750 return 1;
751 }
752
753#else /* !__aarch64__ */
754
755 if (ptrace (PTRACE_SETREGS, tracee->pid, NULL,
756 regs))
757 {
758 errno = EIO;
759 return 1;
760 }
761
762#endif /* __aarch64__ */
763
764 /* Continue the system call until loader starts. */
765
766 if (ptrace (PTRACE_SYSCALL, tracee->pid, NULL, NULL))
767 {
768 errno = EIO;
769 return 1;
770 }
771
772#ifndef REENTRANT
773 /* Now that the loader has started, record the value to use for
774 /proc/self/exe. Don't give up just because strdup fails.
775
776 Note that exec_0 copies the absolute file name into buffer. */
777
778 if (tracee->exec_file)
779 free (tracee->exec_file);
780 tracee->exec_file = strdup (buffer);
781#endif /* REENTRANT */
782
783 again:
784 rc = waitpid (tracee->pid, &wstatus, __WALL);
785 if (rc == -1 && errno == EINTR)
786 goto again;
787
788 if (rc < 0)
789 return 1;
790
791 if (!WIFSTOPPED (wstatus))
792 /* The process has been killed in response to a signal.
793 In this case, simply return 2. */
794 return 2;
795 else
796 {
797 /* Then, check if STATUS is not a syscall-stop, and try again if
798 it isn't. */
799 rc = check_signal (tracee, wstatus);
800
801 if (rc == -1)
802 return 2;
803 else if (rc)
804 goto again;
805
806 /* Retrieve the signal information and determine whether or not
807 the system call has completed. */
808
809 if (ptrace (PTRACE_GETSIGINFO, tracee->pid, 0,
810 &siginfo))
811 return 3;
812
813 if (!syscall_trap_p (&siginfo))
814 {
815 /* Continue. */
816 if (ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0))
817 return 3;
818
819 goto again;
820 }
821 }
822
823#ifdef __aarch64__
824
825 if (aarch64_get_regs (tracee->pid, &original))
826 return 3;
827
828#else /* !__aarch64__ */
829
830 /* The system call has now completed. Get the registers again. */
831
832 if (ptrace (PTRACE_GETREGS, tracee->pid, NULL,
833 &original))
834 return 3;
835
836#endif /* __aarch64__ */
837
838 *regs = original;
839
840 /* Upon failure, wait for the next system call and return
841 success. */
842
843 if (original.SYSCALL_RET_REG)
844 {
845 /* Restore the original stack pointer. */
846 regs->STACK_POINTER = sp;
847
848#ifdef __aarch64__
849 aarch64_set_regs (tracee->pid, regs, false);
850#else /* !__aarch64__ */
851 ptrace (PTRACE_SETREGS, tracee->pid, NULL, regs);
852#endif /* __aarch64__ */
853
854 goto exec_failure;
855 }
856
857 /* Write the loader area to the stack, followed by its size and the
858 original stack pointer. */
859
860 loader = user_alloca (tracee, &original, regs,
861 size + sizeof loader * 2);
862 if (!loader)
863 return 3;
864
865 size1 = size;
866
867#ifndef STACK_GROWS_DOWNWARDS
868
869 NOT_IMPLEMENTED;
870
871#else /* STACK_GROWS_DOWNWARDS */
872
873 if (user_copy (tracee, (unsigned char *) area,
874 loader + sizeof size1 * 2, size)
875 || user_copy (tracee, (unsigned char *) &size1,
876 loader + sizeof size1, sizeof size1))
877 return 3;
878
879 size1 = original.STACK_POINTER;
880
881 if (user_copy (tracee, (unsigned char *) &size1,
882 loader, sizeof size1))
883 return 3;
884
885#endif /* STACK_GROWS_DOWNWARDS */
886
887 /* Continue. */
888 if (ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0))
889 return 3;
890
891 return 0;
892
893 exec_failure:
894 return 3;
895}
896
897/* Handle a `readlink' or `readlinkat' system call.
898
899 CALLNO is the system call number, and REGS are the current user
900 registers of the TRACEE.
901
902 If the file name specified in either a `readlink' or `readlinkat'
903 system call is `/proc/self/exe', write the name of the executable
904 being run into the buffer specified in the system call. Do not
905 handle relative file names at the moment.
906
907 Return the number of bytes written to the tracee's buffer in
908 *RESULT.
909
910 Value is 0 upon success. Value is 1 upon failure, and 2 if the
911 system call has been emulated. */
912
913static int
914handle_readlinkat (USER_WORD callno, USER_REGS_STRUCT *regs,
915 struct exec_tracee *tracee, USER_WORD *result)
916{
917#ifdef REENTRANT
918 /* readlinkat cannot be handled specially when the library is built
919 to be reentrant, as the file name information cannot be
920 recorded. */
921 return 0;
922#else /* !REENTRANT */
923
924 char buffer[PATH_MAX + 1];
925 USER_WORD address, return_buffer, size;
926 size_t length;
927
928 /* Read the file name. */
929
930#ifdef READLINK_SYSCALL
931 if (callno == READLINK_SYSCALL)
932 {
933 address = regs->SYSCALL_ARG_REG;
934 return_buffer = regs->SYSCALL_ARG1_REG;
935 size = regs->SYSCALL_ARG2_REG;
936 }
937 else
938#endif /* READLINK_SYSCALL */
939 {
940 address = regs->SYSCALL_ARG1_REG;
941 return_buffer = regs->SYSCALL_ARG2_REG;
942 size = regs->SYSCALL_ARG3_REG;
943 }
944
945 read_memory (tracee, buffer, PATH_MAX, address);
946
947 /* Make sure BUFFER is NULL terminated. */
948
949 if (!memchr (buffer, '\0', PATH_MAX))
950 {
951 errno = ENAMETOOLONG;
952 return 1;
953 }
954
955 /* Now check if the caller is looking for /proc/self/exe.
956
957 dirfd can be ignored, as for now only absolute file names are
958 handled. FIXME. */
959
960 if (strcmp (buffer, "/proc/self/exe") || !tracee->exec_file)
961 return 0;
962
963 /* Copy over tracee->exec_file. Truncate it to PATH_MAX, length, or
964 size, whichever is less. */
965
966 length = strlen (tracee->exec_file);
967 length = MIN (size, MIN (PATH_MAX, length));
968 strncpy (buffer, tracee->exec_file, length);
969
970 if (user_copy (tracee, (unsigned char *) buffer,
971 return_buffer, length))
972 {
973 errno = EIO;
974 return 1;
975 }
976
977 *result = length;
978 return 2;
979#endif /* REENTRANT */
980}
981
982/* Process the system call at which TRACEE is stopped. If the system
983 call is not known or not exec, send TRACEE on its way. Otherwise,
984 rewrite it to load the loader and perform an appropriate action. */
985
986static void
987process_system_call (struct exec_tracee *tracee)
988{
989 USER_REGS_STRUCT regs;
990 int rc, wstatus, save_errno;
991 USER_WORD callno, sp;
992 USER_WORD result;
993 bool reporting_error;
994
995#ifdef __aarch64__
996 rc = aarch64_get_regs (tracee->pid, &regs);
997#else /* !__aarch64__ */
998 rc = ptrace (PTRACE_GETREGS, tracee->pid, NULL,
999 &regs);
1000#endif /* __aarch64__ */
1001
1002 /* TODO: what to do if this fails? */
1003 if (rc < 0)
1004 return;
1005
1006 /* Save the stack pointer. */
1007 sp = regs.STACK_POINTER;
1008
1009 /* Now dispatch based on the system call. */
1010 callno = regs.SYSCALL_NUM_REG;
1011 switch (callno)
1012 {
1013 case EXEC_SYSCALL:
1014
1015 /* exec system calls should be handled synchronously. */
1016 assert (!tracee->waiting_for_syscall);
1017 rc = handle_exec (tracee, &regs);
1018
1019 switch (rc)
1020 {
1021 case 3:
1022 /* It's too late to do anything about this error,. */
1023 break;
1024
1025 case 2:
1026 /* The process has gone away. */
1027 remove_tracee (tracee);
1028 break;
1029
1030 case 1:
1031 /* An error has occured; errno is set to the error. */
1032 goto report_syscall_error;
1033 }
1034
1035 break;
1036
1037#ifdef READLINK_SYSCALL
1038 case READLINK_SYSCALL:
1039#endif /* READLINK_SYSCALL */
1040 case READLINKAT_SYSCALL:
1041
1042 /* Handle this readlinkat system call. */
1043 rc = handle_readlinkat (callno, &regs, tracee,
1044 &result);
1045
1046 /* rc means the same as in `handle_exec'. */
1047
1048 if (rc == 1)
1049 goto report_syscall_error;
1050 else if (rc == 2)
1051 goto emulate_syscall;
1052
1053 /* Fallthrough. */
1054
1055 default:
1056 /* Don't wait for the system call to finish; instead, the system
1057 will DTRT upon the next call to PTRACE_SYSCALL after the
1058 syscall-trap signal is delivered. */
1059
1060 rc = ptrace (PTRACE_SYSCALL, tracee->pid,
1061 NULL, NULL);
1062 if (rc < 0)
1063 return;
1064
1065 tracee->waiting_for_syscall = !tracee->waiting_for_syscall;
1066 }
1067
1068 return;
1069
1070 report_syscall_error:
1071 reporting_error = true;
1072 goto common;
1073
1074 emulate_syscall:
1075 reporting_error = false;
1076 common:
1077
1078 /* Reporting an error or emulating a system call works by setting
1079 the system call number to -1, letting it continue, and then
1080 substituting errno for ENOSYS in the case of an error.
1081
1082 Make sure that the stack pointer is restored to its original
1083 position upon exit, or bad things can happen. */
1084
1085 /* First, save errno; system calls below will clobber it. */
1086 save_errno = errno;
1087
1088 regs.SYSCALL_NUM_REG = -1;
1089 regs.STACK_POINTER = sp;
1090
1091#ifdef __aarch64__
1092 if (aarch64_set_regs (tracee->pid, &regs, true))
1093 return;
1094#else /* !__aarch64__ */
1095
1096#ifdef __arm__
1097 /* On ARM systems, a special request is used to update the system
1098 call number as known to the kernel. In addition, the system call
1099 number must be valid, so use `tuxcall'. Hopefully, nobody will
1100 run this on a kernel with Tux. */
1101
1102 if (ptrace (PTRACE_SET_SYSCALL, tracee->pid, NULL, 222))
1103 return;
1104#endif /* __arm__ */
1105
1106 if (ptrace (PTRACE_SETREGS, tracee->pid, NULL, &regs))
1107 return;
1108#endif /* __aarch64__ */
1109
1110 /* Do this invalid system call. */
1111 if (ptrace (PTRACE_SYSCALL, tracee->pid, NULL, NULL))
1112 return;
1113
1114 again1:
1115 rc = waitpid (tracee->pid, &wstatus, __WALL);
1116 if (rc == -1 && errno == EINTR)
1117 goto again1;
1118
1119 /* Return if waitpid fails. */
1120
1121 if (rc == -1)
1122 return;
1123
1124 /* If the process received a signal, see if the signal is SIGSYS and
1125 from seccomp. If so, discard it. */
1126
1127 if (WIFSTOPPED (wstatus))
1128 {
1129 rc = check_signal (tracee, wstatus);
1130
1131 if (rc == -1)
1132 return;
1133 else if (rc)
1134 goto again1;
1135 }
1136
1137 if (!WIFSTOPPED (wstatus))
1138 /* The process has been killed in response to a signal. In this
1139 case, simply unlink the tracee and return. */
1140 remove_tracee (tracee);
1141 else if (reporting_error)
1142 {
1143#ifdef __mips__
1144 /* MIPS systems place errno in v0 and set a3 to 1. */
1145 regs.gregs[2] = save_errno;
1146 regs.gregs[7] = 1;
1147#else /* !__mips__ */
1148 regs.SYSCALL_RET_REG = -save_errno;
1149#endif /* __mips__ */
1150
1151 /* Report errno. */
1152#ifdef __aarch64__
1153 aarch64_set_regs (tracee->pid, &regs, false);
1154#else /* !__aarch64__ */
1155 ptrace (PTRACE_SETREGS, tracee->pid, NULL, &regs);
1156#endif /* __aarch64__ */
1157
1158 /* Now wait for the next system call to happen. */
1159 ptrace (PTRACE_SYSCALL, tracee->pid, NULL, NULL);
1160 }
1161 else
1162 {
1163 /* No error is being reported. Return the result in the
1164 appropriate registers. */
1165
1166#ifdef __mips__
1167 /* MIPS systems place errno in v0 and set a3 to 1. */
1168 regs.gregs[2] = result;
1169 regs.gregs[7] = 0;
1170#else /* !__mips__ */
1171 regs.SYSCALL_RET_REG = result;
1172#endif /* __mips__ */
1173
1174 /* Report errno. */
1175#ifdef __aarch64__
1176 aarch64_set_regs (tracee->pid, &regs, false);
1177#else /* !__aarch64__ */
1178 ptrace (PTRACE_SETREGS, tracee->pid, NULL, &regs);
1179#endif /* __aarch64__ */
1180
1181 /* Now wait for the next system call to happen. */
1182 ptrace (PTRACE_SYSCALL, tracee->pid, NULL, NULL);
1183 }
1184}
1185
1186
1187
1188/* Like `execve', but asks the parent to begin tracing this thread.
1189 Fail if tracing is unsuccessful. */
1190
1191int
1192tracing_execve (const char *file, char *const *argv,
1193 char *const *envp)
1194{
1195 int rc;
1196
1197 /* Start tracing self. */
1198 rc = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
1199 if (rc)
1200 return rc;
1201
1202 /* Notify the parent to enter signal-delivery-stop. */
1203 raise (SIGSTOP);
1204 return execve (file, argv, envp);
1205}
1206
1207/* Wait for PID to trace itself, and make a record of that process.
1208 Value is 1 or 2 upon failure, 0 otherwise. Make sure that SIGCHLD
1209 is blocked around calls to this function.
1210
1211 If failure occurs because PID exited, value is 2; upon any other
1212 kind of failure, value is 1. */
1213
1214int
1215after_fork (pid_t pid)
1216{
1217 int wstatus, rc, flags;
1218 struct exec_tracee *tracee;
1219
1220 /* First, wait for something to happen to PID. */
1221 again:
1222 rc = waitpid (pid, &wstatus, __WALL);
1223 if (rc != pid && errno == EINTR)
1224 goto again;
1225
1226 if (rc != pid)
1227 return 1;
1228
1229 /* If the child exited (or in general wasn't traced), return 2. */
1230
1231 if (!WIFSTOPPED (wstatus))
1232 return 2;
1233
1234 /* Apply required options to the child, so that the kernel
1235 automatically traces children and makes it easy to differentiate
1236 between system call traps and other kinds of traps. */
1237
1238 flags = PTRACE_O_TRACECLONE;
1239 flags |= PTRACE_O_TRACEVFORK;
1240 flags |= PTRACE_O_TRACEFORK;
1241 flags |= PTRACE_O_TRACESYSGOOD;
1242 flags |= PTRACE_O_TRACEEXIT;
1243
1244 rc = ptrace (PTRACE_SETOPTIONS, pid, 0, flags);
1245
1246 if (rc)
1247 {
1248 /* If the kernel can't trace child processes upon creation and
1249 exit, then it can't work reliably. */
1250 ptrace (PTRACE_DETACH, pid, 0, 0);
1251 return 1;
1252 }
1253
1254 /* Request that the child stop upon the next system call. */
1255 rc = ptrace (PTRACE_SYSCALL, pid, 0, 0);
1256 if (rc)
1257 return 1;
1258
1259 /* Enter the child in `tracing_processes'. */
1260
1261 if (free_tracees)
1262 {
1263 tracee = free_tracees;
1264 free_tracees = free_tracees->next;
1265 }
1266 else
1267 tracee = malloc (sizeof *tracee);
1268
1269 if (!tracee)
1270 return 1;
1271
1272 tracee->pid = pid;
1273 tracee->next = tracing_processes;
1274 tracee->waiting_for_syscall = false;
1275 tracee->new_child = false;
1276#ifndef REENTRANT
1277 tracee->exec_file = NULL;
1278#endif /* REENTRANT */
1279 tracing_processes = tracee;
1280 return 0;
1281}
1282
1283/* Wait for a child process to exit, like `waitpid'. However, if a
1284 child stops to perform a system call, send it on its way and return
1285 -1. OPTIONS must not contain WUNTRACED. */
1286
1287pid_t
1288exec_waitpid (pid_t pid, int *wstatus, int options)
1289{
1290 int status;
1291 struct exec_tracee *tracee;
1292 siginfo_t siginfo;
1293
1294 pid = waitpid (pid, &status, options | __WALL);
1295 if (pid < 0)
1296 return pid;
1297
1298 /* Copy status into *WSTATUS if specified. */
1299 if (wstatus)
1300 *wstatus = status;
1301
1302 /* WIFSTOPPED (status) means that the process has been stopped in
1303 response to a system call. Find its tracee and process the
1304 system call. */
1305
1306 if (WIFSTOPPED (status))
1307 {
1308 tracee = find_tracee (pid);
1309
1310 if (!tracee || tracee->new_child)
1311 {
1312 if (WSTOPSIG (status) == SIGSTOP)
1313 /* A new process has been created and stopped. Record
1314 it now. */
1315 handle_clone (tracee, pid);
1316
1317 return -1;
1318 }
1319
1320 /* Now extract the stop signal, including ptrace event bits. */
1321 status &= 0xfff00;
1322 status = status >> 8;
1323
1324 switch (status)
1325 {
1326 case SIGTRAP:
1327 /* Now, use PTRACE_GETSIGINFO to determine whether or not the
1328 signal was delivered in response to a system call. */
1329
1330 if (ptrace (PTRACE_GETSIGINFO, pid, 0, &siginfo))
1331 return -1;
1332
1333 if (!syscall_trap_p (&siginfo))
1334 {
1335 if (siginfo.si_code < 0)
1336 /* SIGTRAP delivered from userspace. Pass it on. */
1337 ptrace (PTRACE_SYSCALL, pid, 0, SIGTRAP);
1338 else
1339 ptrace (PTRACE_SYSCALL, pid, 0, 0);
1340
1341 return -1;
1342 }
1343
1344 case SIGTRAP | 0x80: /* SIGTRAP | 0x80 specifically refers to
1345 system call traps. */
1346 /* Otherwise, process the system call and continue waiting. */
1347 process_system_call (tracee);
1348 return -1;
1349
1350 case SIGTRAP | (PTRACE_EVENT_EXIT << 8):
1351 /* The tracee has exited. Make it finish correctly. */
1352 ptrace (PTRACE_SYSCALL, pid, 0, 0);
1353 remove_tracee (tracee);
1354 return -1;
1355
1356 case SIGTRAP | (PTRACE_EVENT_FORK << 8):
1357 case SIGTRAP | (PTRACE_EVENT_VFORK << 8):
1358 case SIGTRAP | (PTRACE_EVENT_CLONE << 8):
1359
1360 /* Both PTRACE_EVENT_CLONE and SIGSTOP must arrive before a
1361 process is continued. Otherwise, its parent's cmdline
1362 cannot be obtained and propagated.
1363
1364 If the PID of the new process is currently not being
1365 traced, create a new tracee. Set `new_child' to true,
1366 and copy over the old command line in preparation for a
1367 SIGSTOP signal being delivered to it.
1368
1369 Otherwise, start the tracee running until the next
1370 syscall. */
1371
1372 handle_clone_prepare (tracee);
1373
1374 /* These events are handled by tracing SIGSTOP signals sent
1375 to unknown tracees. Make sure not to pass through
1376 status, as there's no signal really being delivered. */
1377 ptrace (PTRACE_SYSCALL, pid, 0, 0);
1378 return -1;
1379
1380#ifdef SIGSYS
1381 case SIGSYS:
1382 if (ptrace (PTRACE_GETSIGINFO, pid, 0, &siginfo))
1383 return -1;
1384
1385 /* Continue the process until the next syscall, but don't
1386 pass through the signal if an emulated syscall led to
1387 it. */
1388#ifdef HAVE_SIGINFO_T_SI_SYSCALL
1389#ifndef __arm__
1390 ptrace (PTRACE_SYSCALL, pid, 0, ((siginfo.si_code == SYS_SECCOMP
1391 && siginfo.si_syscall == -1)
1392 ? 0 : status));
1393#else /* __arm__ */
1394 ptrace (PTRACE_SYSCALL, pid, 0, ((siginfo.si_code == SYS_SECCOMP
1395 && siginfo.si_syscall == 222)
1396 ? 0 : status));
1397#endif /* !__arm__ */
1398#else /* !HAVE_SIGINFO_T_SI_SYSCALL */
1399 /* Drop this signal, since what caused it is unknown. */
1400 ptrace (PTRACE_SYSCALL, pid, 0, 0);
1401#endif /* HAVE_SIGINFO_T_SI_SYSCALL */
1402 return -1;
1403#endif /* SIGSYS */
1404
1405 default:
1406 /* Continue the process until the next syscall. */
1407 ptrace (PTRACE_SYSCALL, pid, 0, status);
1408 return -1;
1409 }
1410 }
1411 else
1412 {
1413 /* The process has exited. Unlink the associated tracee. */
1414 tracee = find_tracee (pid);
1415
1416 if (tracee)
1417 remove_tracee (tracee);
1418
1419 return pid;
1420 }
1421}
1422
1423
1424
1425/* Initialize the exec library. LOADER should be the file name of the
1426 loader binary; it is not copied. */
1427
1428void
1429exec_init (const char *loader)
1430{
1431 loader_name = loader;
1432}