diff options
| author | Po Lu | 2023-08-07 08:51:11 +0800 |
|---|---|---|
| committer | Po Lu | 2023-08-07 08:51:11 +0800 |
| commit | c71a520d1da636a722cf87b46534ca3b5aafbc7b (patch) | |
| tree | 95a3099c065800f60602e0a403b551a6d6dba139 /exec | |
| parent | 18e7bc87521e3c48b819cfe4a113f532ba905561 (diff) | |
| parent | 9a9f73041d09d2da7ed562c7ffae0d9519562fba (diff) | |
| download | emacs-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.in | 140 | ||||
| -rw-r--r-- | exec/README | 3 | ||||
| -rw-r--r-- | exec/config-mips.m4.in | 42 | ||||
| -rwxr-xr-x | exec/config.guess | 1768 | ||||
| -rw-r--r-- | exec/config.h.in | 358 | ||||
| -rwxr-xr-x | exec/config.sub | 1890 | ||||
| -rw-r--r-- | exec/configure.ac | 537 | ||||
| -rw-r--r-- | exec/deps.mk | 21 | ||||
| -rw-r--r-- | exec/exec.c | 1235 | ||||
| -rw-r--r-- | exec/exec.h | 201 | ||||
| -rw-r--r-- | exec/exec1.c | 94 | ||||
| -rwxr-xr-x | exec/install-sh | 541 | ||||
| -rw-r--r-- | exec/loader-aarch64.s | 187 | ||||
| -rw-r--r-- | exec/loader-armeabi.s | 204 | ||||
| -rw-r--r-- | exec/loader-mips64el.s | 234 | ||||
| -rw-r--r-- | exec/loader-mipsel.s | 236 | ||||
| -rw-r--r-- | exec/loader-x86.s | 203 | ||||
| -rw-r--r-- | exec/loader-x86_64.s | 195 | ||||
| -rw-r--r-- | exec/mipsel-user.h | 43 | ||||
| -rw-r--r-- | exec/mipsfpu.c | 289 | ||||
| -rw-r--r-- | exec/mipsfpu.h | 82 | ||||
| -rw-r--r-- | exec/test.c | 105 | ||||
| -rw-r--r-- | exec/trace.c | 1432 |
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@ | ||
| 38 | LOADERFLAGS = @LOADERFLAGS@ | ||
| 39 | FIND_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 | |||
| 49 | AUTO_DEPEND = @AUTO_DEPEND@ | ||
| 50 | DEPDIR = deps | ||
| 51 | ifeq ($(AUTO_DEPEND),yes) | ||
| 52 | DEPFLAGS = -MMD -MF $(DEPDIR)/$*.d -MP | ||
| 53 | -include $(OBJS:%.o=$(DEPDIR)/%.d) | ||
| 54 | -include $(DEPDIR)/test.d | ||
| 55 | -include $(DEPDIR)/exec1.d | ||
| 56 | else | ||
| 57 | DEPFLAGS = | ||
| 58 | include $(srcdir)/deps.mk | ||
| 59 | endif | ||
| 60 | |||
| 61 | # Set up the appropriate targets. | ||
| 62 | |||
| 63 | all: libexec.a loader | ||
| 64 | |||
| 65 | # Set up automatic Makefile regeneration. | ||
| 66 | |||
| 67 | $(srcdir)/configure: $(srcdir)/configure.ac | ||
| 68 | cd $(srcdir) && autoreconf | ||
| 69 | |||
| 70 | config.status: $(srcdir)/configure | ||
| 71 | if [ -x config.status ]; then \ | ||
| 72 | ./config.status --recheck; \ | ||
| 73 | else \ | ||
| 74 | $(srcdir)/configure; \ | ||
| 75 | fi | ||
| 76 | |||
| 77 | Makefile: 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 | |||
| 91 | config-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 | |||
| 97 | libexec.a: $(OBJS) | ||
| 98 | $(AR) cru $(ARFLAGS) $@ $^ | ||
| 99 | |||
| 100 | # And loader. | ||
| 101 | |||
| 102 | loader: $(LOADOBJS) | ||
| 103 | $(LD) -o $@ $(LOADERFLAGS) $(LOADOBJS) | ||
| 104 | |||
| 105 | # And test. | ||
| 106 | |||
| 107 | test: test.o libexec.a | ||
| 108 | $(CC) $(LDFLAGS) $< libexec.a -o $@ | ||
| 109 | |||
| 110 | # And exec1. | ||
| 111 | |||
| 112 | exec1: 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 | ||
| 118 | clean: | ||
| 119 | rm -f *.o *.a loader test exec1 *.s.s | ||
| 120 | ifeq ($(AUTO_DEPEND),yes) | ||
| 121 | rm -rf deps/*.d | ||
| 122 | endif | ||
| 123 | |||
| 124 | distclean: clean | ||
| 125 | rm -f Makefile config.status config.h config-mips.m4 | ||
| 126 | |||
| 127 | maintainer-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 | |||
| 134 | extraclean: 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) | ||
| 140 | bootstrap-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 @@ | |||
| 1 | This directory holds the source code to a library used to replace the | ||
| 2 | `execve' and `execveat' system calls, used by the Android port of | ||
| 3 | Emacs 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 @@ | |||
| 1 | dnl Assembler templates for MIPS computers. | ||
| 2 | dnl | ||
| 3 | dnl Copyright (C) 2023 Free Software Foundation, Inc. | ||
| 4 | dnl | ||
| 5 | dnl This file is part of GNU Emacs. | ||
| 6 | dnl | ||
| 7 | dnl GNU Emacs is free software: you can redistribute it and/or modify | ||
| 8 | dnl it under the terms of the GNU General Public License as published by | ||
| 9 | dnl the Free Software Foundation, either version 3 of the License, or | ||
| 10 | dnl (at your option) any later version. | ||
| 11 | dnl | ||
| 12 | dnl GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | dnl but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | dnl GNU General Public License for more details. | ||
| 16 | dnl | ||
| 17 | dnl You should have received a copy of the GNU General Public License | ||
| 18 | dnl along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 19 | |||
| 20 | define(`SYSCALL_open', `ifelse(`@MIPS_N32@',`yes',`6002',`4005')') | ||
| 21 | define(`SYSCALL_close', `ifelse(`@MIPS_N32@',`yes',`6003',`4006')') | ||
| 22 | define(`SYSCALL_mmap', `ifelse(`@MIPS_N32@',`yes',`6009',`4090')') | ||
| 23 | define(`SYSCALL_nanosleep', `ifelse(`@MIPS_N32@',`yes',`6034',`4166')') | ||
| 24 | define(`SYSCALL_exit', `ifelse(`@MIPS_N32@',`yes',`6058',`4001')') | ||
| 25 | define(`SYSCALL_prctl', `ifelse(`@MIPS_N32@',`yes',`6153',`4192')') | ||
| 26 | |||
| 27 | define(`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 | |||
| 36 | define(`RESTORE', `ifelse(`@MIPS_N32@',`yes',` nop',` addi $sp, 32')') | ||
| 37 | |||
| 38 | dnl For mips64. Some assemblers don't want to assemble `daddi'. | ||
| 39 | define(`DADDI2', `ifelse(`@DADDI_BROKEN@',`yes',` li $at, $2 | ||
| 40 | dadd $1, $1, $at',` daddi $1, $2')') | ||
| 41 | define(`DADDI3', `ifelse(`@DADDI_BROKEN@',`yes',` li $at, $3 | ||
| 42 | dadd $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 | |||
| 7 | timestamp='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 | |||
| 45 | me=`echo "$0" | sed -e 's,.*/,,'` | ||
| 46 | |||
| 47 | usage="\ | ||
| 48 | Usage: $0 [OPTION] | ||
| 49 | |||
| 50 | Output the configuration name of the system \`$me' is run on. | ||
| 51 | |||
| 52 | Options: | ||
| 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 | |||
| 57 | Report bugs and patches to <config-patches@gnu.org>." | ||
| 58 | |||
| 59 | version="\ | ||
| 60 | GNU config.guess ($timestamp) | ||
| 61 | |||
| 62 | Originally written by Per Bothner. | ||
| 63 | Copyright 1992-2022 Free Software Foundation, Inc. | ||
| 64 | |||
| 65 | This is free software; see the source for copying conditions. There is NO | ||
| 66 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." | ||
| 67 | |||
| 68 | help=" | ||
| 69 | Try \`$me --help' for more information." | ||
| 70 | |||
| 71 | # Parse command line | ||
| 72 | while 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 | ||
| 90 | done | ||
| 91 | |||
| 92 | if test $# != 0; then | ||
| 93 | echo "$me: too many arguments$help" >&2 | ||
| 94 | exit 1 | ||
| 95 | fi | ||
| 96 | |||
| 97 | # Just in case it came from the environment. | ||
| 98 | GUESS= | ||
| 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 | |||
| 110 | tmp= | ||
| 111 | # shellcheck disable=SC2172 | ||
| 112 | trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 | ||
| 113 | |||
| 114 | set_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) | ||
| 143 | if test -f /.attbin/uname ; then | ||
| 144 | PATH=$PATH:/.attbin ; export PATH | ||
| 145 | fi | ||
| 146 | |||
| 147 | UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown | ||
| 148 | UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown | ||
| 149 | UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown | ||
| 150 | UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown | ||
| 151 | |||
| 152 | case $UNAME_SYSTEM in | ||
| 153 | Linux|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 | ;; | ||
| 189 | esac | ||
| 190 | |||
| 191 | # Note: order is significant - the case branches are not exclusive. | ||
| 192 | |||
| 193 | case $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 | } | ||
| 550 | EOF | ||
| 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 | } | ||
| 638 | EOF | ||
| 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 | } | ||
| 741 | EOF | ||
| 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 | } | ||
| 799 | EOF | ||
| 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 | ||
| 1091 | EOF | ||
| 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 | ||
| 1166 | EOF | ||
| 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 | ;; | ||
| 1557 | esac | ||
| 1558 | |||
| 1559 | # Do we have a guess based on uname results? | ||
| 1560 | if test "x$GUESS" != x; then | ||
| 1561 | echo "$GUESS" | ||
| 1562 | exit | ||
| 1563 | fi | ||
| 1564 | |||
| 1565 | # No uname command or uname output not recognized. | ||
| 1566 | set_cc_for_build | ||
| 1567 | cat > "$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 | ||
| 1580 | main () | ||
| 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 | } | ||
| 1694 | EOF | ||
| 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. | ||
| 1700 | test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } | ||
| 1701 | |||
| 1702 | echo "$0: unable to guess system type" >&2 | ||
| 1703 | |||
| 1704 | case $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 | |||
| 1709 | NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize | ||
| 1710 | the system type. Please install a C compiler and try again. | ||
| 1711 | EOF | ||
| 1712 | ;; | ||
| 1713 | esac | ||
| 1714 | |||
| 1715 | cat >&2 <<EOF | ||
| 1716 | |||
| 1717 | This script (version $timestamp), has failed to recognize the | ||
| 1718 | operating system you are using. If your script is old, overwrite *all* | ||
| 1719 | copies of config.guess and config.sub with the latest versions from: | ||
| 1720 | |||
| 1721 | https://git.savannah.gnu.org/cgit/config.git/plain/config.guess | ||
| 1722 | and | ||
| 1723 | https://git.savannah.gnu.org/cgit/config.git/plain/config.sub | ||
| 1724 | EOF | ||
| 1725 | |||
| 1726 | our_year=`echo $timestamp | sed 's,-.*,,'` | ||
| 1727 | thisyear=`date +%Y` | ||
| 1728 | # shellcheck disable=SC2003 | ||
| 1729 | script_age=`expr "$thisyear" - "$our_year"` | ||
| 1730 | if test "$script_age" -lt 3 ; then | ||
| 1731 | cat >&2 <<EOF | ||
| 1732 | |||
| 1733 | If $0 has already been updated, send the following data and any | ||
| 1734 | information you think might be pertinent to config-patches@gnu.org to | ||
| 1735 | provide the necessary information to handle your system. | ||
| 1736 | |||
| 1737 | config.guess timestamp = $timestamp | ||
| 1738 | |||
| 1739 | uname -m = `(uname -m) 2>/dev/null || echo unknown` | ||
| 1740 | uname -r = `(uname -r) 2>/dev/null || echo unknown` | ||
| 1741 | uname -s = `(uname -s) 2>/dev/null || echo unknown` | ||
| 1742 | uname -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 | |||
| 1747 | hostinfo = `(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 | |||
| 1754 | UNAME_MACHINE = "$UNAME_MACHINE" | ||
| 1755 | UNAME_RELEASE = "$UNAME_RELEASE" | ||
| 1756 | UNAME_SYSTEM = "$UNAME_SYSTEM" | ||
| 1757 | UNAME_VERSION = "$UNAME_VERSION" | ||
| 1758 | EOF | ||
| 1759 | fi | ||
| 1760 | |||
| 1761 | exit 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 | |||
| 5 | This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is free software: you can redistribute it and/or modify it | ||
| 8 | under the terms of the GNU General Public License as published by the | ||
| 9 | Free Software Foundation, either version 3 of the License, or (at your | ||
| 10 | option) any later version. | ||
| 11 | |||
| 12 | GNU Emacs is distributed in the hope that it will be useful, but | ||
| 13 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | 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 | /* 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 | ||
| 336 | typedef 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 | |||
| 7 | timestamp='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 | |||
| 62 | me=`echo "$0" | sed -e 's,.*/,,'` | ||
| 63 | |||
| 64 | usage="\ | ||
| 65 | Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS | ||
| 66 | |||
| 67 | Canonicalize a configuration name. | ||
| 68 | |||
| 69 | Options: | ||
| 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 | |||
| 74 | Report bugs and patches to <config-patches@gnu.org>." | ||
| 75 | |||
| 76 | version="\ | ||
| 77 | GNU config.sub ($timestamp) | ||
| 78 | |||
| 79 | Copyright 1992-2022 Free Software Foundation, Inc. | ||
| 80 | |||
| 81 | This is free software; see the source for copying conditions. There is NO | ||
| 82 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." | ||
| 83 | |||
| 84 | help=" | ||
| 85 | Try \`$me --help' for more information." | ||
| 86 | |||
| 87 | # Parse command line | ||
| 88 | while 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 | ||
| 112 | done | ||
| 113 | |||
| 114 | case $# 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;; | ||
| 120 | esac | ||
| 121 | |||
| 122 | # Split fields of configuration type | ||
| 123 | # shellcheck disable=SC2162 | ||
| 124 | saved_IFS=$IFS | ||
| 125 | IFS="-" read field1 field2 field3 field4 <<EOF | ||
| 126 | $1 | ||
| 127 | EOF | ||
| 128 | IFS=$saved_IFS | ||
| 129 | |||
| 130 | # Separate into logical components for further validation | ||
| 131 | case $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 | ;; | ||
| 656 | esac | ||
| 657 | |||
| 658 | # Decode 1-component or ad-hoc basic machines | ||
| 659 | case $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 | ||
| 943 | EOF | ||
| 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 | ;; | ||
| 968 | esac | ||
| 969 | |||
| 970 | unset -v basic_machine | ||
| 971 | |||
| 972 | # Decode basic machines in the full and proper CPU-Company form. | ||
| 973 | case $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 | ;; | ||
| 1293 | esac | ||
| 1294 | |||
| 1295 | # Here we canonicalize certain aliases for manufacturers. | ||
| 1296 | case $vendor in | ||
| 1297 | digital*) | ||
| 1298 | vendor=dec | ||
| 1299 | ;; | ||
| 1300 | commodore*) | ||
| 1301 | vendor=cbm | ||
| 1302 | ;; | ||
| 1303 | *) | ||
| 1304 | ;; | ||
| 1305 | esac | ||
| 1306 | |||
| 1307 | # Decode manufacturer-specific aliases for certain operating systems. | ||
| 1308 | |||
| 1309 | if test x$basic_os != x | ||
| 1310 | then | ||
| 1311 | |||
| 1312 | # First recognize some ad-hoc cases, or perhaps split kernel-os, or else just | ||
| 1313 | # set os. | ||
| 1314 | case $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 | ||
| 1332 | EOF | ||
| 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 | ;; | ||
| 1348 | esac | ||
| 1349 | |||
| 1350 | # Now, normalize the OS (knowing we just have one component, it's not a kernel, | ||
| 1351 | # etc.) | ||
| 1352 | case $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 | ;; | ||
| 1516 | esac | ||
| 1517 | |||
| 1518 | else | ||
| 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 | |||
| 1530 | kernel= | ||
| 1531 | case $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 | ;; | ||
| 1708 | esac | ||
| 1709 | |||
| 1710 | fi | ||
| 1711 | |||
| 1712 | # Now, validate our (potentially fixed-up) OS. | ||
| 1713 | case $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 | ;; | ||
| 1769 | esac | ||
| 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. | ||
| 1773 | case $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 | ;; | ||
| 1802 | esac | ||
| 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. | ||
| 1806 | case $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 | ;; | ||
| 1880 | esac | ||
| 1881 | |||
| 1882 | echo "$cpu-$vendor-${kernel:+$kernel-}$os" | ||
| 1883 | exit | ||
| 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 @@ | |||
| 1 | dnl Autoconf script for GNU Emacs's exec library. | ||
| 2 | dnl To rebuild the 'configure' script from this, execute the command | ||
| 3 | dnl autoconf | ||
| 4 | dnl in the directory containing this script. | ||
| 5 | dnl If you changed any AC_DEFINES, also run autoheader. | ||
| 6 | dnl | ||
| 7 | dnl Copyright (C) 2023 Free Software Foundation, Inc. | ||
| 8 | dnl | ||
| 9 | dnl This file is part of GNU Emacs. | ||
| 10 | dnl | ||
| 11 | dnl GNU Emacs is free software: you can redistribute it and/or modify | ||
| 12 | dnl it under the terms of the GNU General Public License as published by | ||
| 13 | dnl the Free Software Foundation, either version 3 of the License, or | ||
| 14 | dnl (at your option) any later version. | ||
| 15 | dnl | ||
| 16 | dnl GNU Emacs is distributed in the hope that it will be useful, | ||
| 17 | dnl but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | dnl GNU General Public License for more details. | ||
| 20 | dnl | ||
| 21 | dnl You should have received a copy of the GNU General Public License | ||
| 22 | dnl along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 23 | |||
| 24 | AC_PREREQ([2.65]) | ||
| 25 | AC_INIT([libexec], [30.0.50], [bug-gnu-emacs@gnu.org], [], | ||
| 26 | [https://www.gnu.org/software/emacs/]) | ||
| 27 | |||
| 28 | AH_TOP([/* Copyright (C) 2023 Free Software Foundation, Inc. | ||
| 29 | |||
| 30 | This file is part of GNU Emacs. | ||
| 31 | |||
| 32 | GNU Emacs is free software: you can redistribute it and/or modify it | ||
| 33 | under the terms of the GNU General Public License as published by the | ||
| 34 | Free Software Foundation, either version 3 of the License, or (at your | ||
| 35 | option) any later version. | ||
| 36 | |||
| 37 | GNU Emacs is distributed in the hope that it will be useful, but | ||
| 38 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 39 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 40 | General Public License for more details. | ||
| 41 | |||
| 42 | You should have received a copy of the GNU General Public License | ||
| 43 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */]) | ||
| 44 | |||
| 45 | AC_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 | |||
| 50 | AC_USE_SYSTEM_EXTENSIONS | ||
| 51 | AC_PROG_CC | ||
| 52 | AC_PROG_CPP | ||
| 53 | AC_PROG_INSTALL | ||
| 54 | |||
| 55 | AC_TYPE_UINT8_T | ||
| 56 | AC_TYPE_UINT16_T | ||
| 57 | AC_TYPE_UINT32_T | ||
| 58 | AC_TYPE_UINT64_T | ||
| 59 | AC_TYPE_UINTPTR_T | ||
| 60 | AC_TYPE_SIZE_T | ||
| 61 | AC_TYPE_SSIZE_T | ||
| 62 | AC_TYPE_PID_T | ||
| 63 | |||
| 64 | AC_HEADER_STDBOOL | ||
| 65 | AC_CHECK_FUNCS([getpagesize stpcpy stpncpy]) | ||
| 66 | AC_CHECK_DECLS([stpcpy, stpncpy]) | ||
| 67 | AC_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 | ]])])]) | ||
| 75 | AC_CHECK_HEADERS([sys/param.h sys/uio.h]) | ||
| 76 | AC_CHECK_MEMBERS([siginfo_t.si_syscall], [], [], | ||
| 77 | [[ | ||
| 78 | #include <signal.h> | ||
| 79 | ]]) | ||
| 80 | |||
| 81 | AH_BOTTOM([ | ||
| 82 | #ifdef HAVE_STDBOOL_H | ||
| 83 | # include <stdbool.h> | ||
| 84 | #else | ||
| 85 | # ifndef HAVE__BOOL | ||
| 86 | # ifdef __cplusplus | ||
| 87 | typedef 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 | |||
| 111 | AC_C_BIGENDIAN | ||
| 112 | |||
| 113 | AH_TEMPLATE([SYSCALL_HEADER], [Define to header holding system call numbers.]) | ||
| 114 | AH_TEMPLATE([USER_HEADER], [Define to header holding USER_REGS_STRUCT.]) | ||
| 115 | AH_TEMPLATE([USER_REGS_STRUCT], [Define to structure holding user registers.]) | ||
| 116 | AH_TEMPLATE([SYSCALL_NUM_REG], [Define to register holding the system call number.]) | ||
| 117 | AH_TEMPLATE([SYSCALL_ARG_REG], [Define to register holding arg0 to system calls.]) | ||
| 118 | AH_TEMPLATE([SYSCALL_ARG1_REG], [Define to register holding arg1 to system calls.]) | ||
| 119 | AH_TEMPLATE([SYSCALL_ARG2_REG], [Define to register holding arg2 to system calls.]) | ||
| 120 | AH_TEMPLATE([SYSCALL_ARG3_REG], [Define to register holding arg3 to system calls.]) | ||
| 121 | AH_TEMPLATE([SYSCALL_RET_REG], [Define to register holding value of system calls.]) | ||
| 122 | AH_TEMPLATE([STACK_POINTER], [Define to register holding the stack pointer.]) | ||
| 123 | AH_TEMPLATE([EXEC_SYSCALL], [Define to number of the `exec' system call.]) | ||
| 124 | AH_TEMPLATE([USER_WORD], [Define to word type used by tracees.]) | ||
| 125 | AH_TEMPLATE([EXEC_64], [Define to 1 if the system utilizes 64-bit ELF.]) | ||
| 126 | AH_TEMPLATE([STACK_GROWS_DOWNWARDS], [Define to 1 if the stack grows downwards.]) | ||
| 127 | AH_TEMPLATE([ABI_RED_ZONE], [Define to number of reserved bytes past the stack frame.]) | ||
| 128 | AH_TEMPLATE([EXECUTABLE_BASE], [Virtual address for loading PIC executables]) | ||
| 129 | AH_TEMPLATE([INTERPRETER_BASE], [Virtual address for loading PIC interpreters]) | ||
| 130 | AH_TEMPLATE([CLONE_SYSCALL], [Define to number of the `clone' system call.]) | ||
| 131 | AH_TEMPLATE([CLONE3_SYSCALL], [Define to number of the `clone3' system call.]) | ||
| 132 | AH_TEMPLATE([READLINK_SYSCALL], [Define to number of the `readlink' system call.]) | ||
| 133 | AH_TEMPLATE([READLINKAT_SYSCALL], [Define to number of the `readlinkat' system call.]) | ||
| 134 | AH_TEMPLATE([REENTRANT], [Define to 1 if the library is used within a signal handler.]) | ||
| 135 | |||
| 136 | AC_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. | ||
| 140 | AS_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 | |||
| 147 | AC_ARG_VAR([M4], [`m4' preprocessor command.]) | ||
| 148 | AC_ARG_VAR([AS], [`as' assembler command.]) | ||
| 149 | AC_ARG_VAR([LD], [`ld' linker command.]) | ||
| 150 | |||
| 151 | # Check for a working m4. | ||
| 152 | AC_CHECK_PROGS([M4], [gm4 m4], | ||
| 153 | [AC_MSG_ERROR([Cannot find m4])]) | ||
| 154 | |||
| 155 | # Check for a working assembler. | ||
| 156 | AC_CHECK_TOOL([AS], [as], | ||
| 157 | [AC_MSG_ERROR([Cannot find a working assembler])]) | ||
| 158 | |||
| 159 | # And ar. | ||
| 160 | AC_CHECK_TOOL([AR], [ar], | ||
| 161 | [AC_MSG_ERROR([Cannot find a working ar])]) | ||
| 162 | |||
| 163 | # And ld. | ||
| 164 | AC_CHECK_TOOL([LD], [ld], | ||
| 165 | [AC_MSG_ERROR([Cannot find a working linker])]) | ||
| 166 | |||
| 167 | # Now check if ld is a C compiler. | ||
| 168 | LDPREFIX= | ||
| 169 | AC_CACHE_CHECK([whether ld is a C compiler], | ||
| 170 | [exec_cv_ld_is_cc], | ||
| 171 | [cat <<_ACEOF > conftest.c | ||
| 172 | AC_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. | ||
| 180 | AC_CACHE_CHECK([whether as is a C compiler], | ||
| 181 | [exec_cv_as_is_cc], | ||
| 182 | [cat <<_ACEOF > conftest.c | ||
| 183 | AC_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, | ||
| 192 | AS_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. | ||
| 197 | AS_IF([test "x$exec_cv_as_is_cc" = "xyes"], | ||
| 198 | [ASFLAGS="$ASFLAGS -c"]) | ||
| 199 | |||
| 200 | AC_DEFUN([exec_CHECK_LINUX_CLONE3], | ||
| 201 | [ | ||
| 202 | AC_CHECK_DECL([__NR_clone3], | ||
| 203 | [AC_DEFINE([CLONE3_SYSCALL], [__NR_clone3])], | ||
| 204 | [], [[ | ||
| 205 | #include <asm/unistd.h> | ||
| 206 | ]]) | ||
| 207 | ]) | ||
| 208 | |||
| 209 | AC_DEFUN([exec_CHECK_MIPS_NABI], | ||
| 210 | [ | ||
| 211 | AC_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 | ||
| 218 | OABI in use. | ||
| 219 | #endif /* _MIPS_SIM == _ABIO32 */ | ||
| 220 | #endif /* !__mips64__ */ | ||
| 221 | ]])], [exec_cv_mips_nabi=yes], | ||
| 222 | [exec_cv_mips_nabi=no])]) | ||
| 223 | |||
| 224 | dnl mips64 systems use N64 calling convention, a variant of nabi | ||
| 225 | dnl calling convention. | ||
| 226 | AS_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. | ||
| 233 | exec_loader= | ||
| 234 | is_mips= | ||
| 235 | OBJS="exec.o trace.o" | ||
| 236 | DADDI_BROKEN=no | ||
| 237 | |||
| 238 | AS_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 | |||
| 452 | AC_SUBST([DADDI_BROKEN]) | ||
| 453 | |||
| 454 | MIPS_N32=$exec_cv_mips_nabi | ||
| 455 | |||
| 456 | AC_ARG_VAR([LOADERFLAGS], [Flags used to link the loader.]) | ||
| 457 | AC_ARG_VAR([ARFLAGS], [Flags for the archiver.]) | ||
| 458 | AC_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 | |||
| 463 | AC_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 | |||
| 477 | AS_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 | |||
| 483 | AC_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]) | ||
| 496 | AS_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. | ||
| 500 | AUTO_DEPEND=no | ||
| 501 | AS_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 | |||
| 518 | AC_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 {} ';'"])]) | ||
| 523 | FIND_DELETE=$exec_cv_find_delete | ||
| 524 | AC_SUBST([FIND_DELETE]) | ||
| 525 | |||
| 526 | AC_CONFIG_HEADERS([config.h]) | ||
| 527 | AC_CONFIG_FILES([Makefile config-mips.m4]) | ||
| 528 | |||
| 529 | AC_SUBST([AUTO_DEPEND]) | ||
| 530 | AC_SUBST([LOADERFLAGS]) | ||
| 531 | AC_SUBST([ARFLAGS]) | ||
| 532 | AC_SUBST([ASFLAGS]) | ||
| 533 | AC_SUBST([exec_loader]) | ||
| 534 | AC_SUBST([MIPS_N32]) | ||
| 535 | AC_SUBST([OBJS]) | ||
| 536 | |||
| 537 | AC_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 | |||
| 20 | exec.o: exec.h config.h | ||
| 21 | trace.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 | |||
| 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 (at | ||
| 10 | 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 | #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 | |||
| 50 | static char * | ||
| 51 | rpl_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 | |||
| 74 | static char * | ||
| 75 | rpl_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 | |||
| 164 | static const char * | ||
| 165 | check_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. */ | ||
| 236 | static char loader_area[65536]; | ||
| 237 | |||
| 238 | /* Number of bytes used in that area. */ | ||
| 239 | static 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 | |||
| 246 | struct 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 | |||
| 255 | struct 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 | |||
| 279 | struct 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 | |||
| 314 | static int | ||
| 315 | write_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 | |||
| 355 | static int | ||
| 356 | write_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. */ | ||
| 471 | static struct mips_elf_abi_flags exec_abi, interpreter_abi; | ||
| 472 | |||
| 473 | /* Static storage for interpreter headers. */ | ||
| 474 | static elf_header exec_interpreter_header; | ||
| 475 | |||
| 476 | /* Pointer to the ELF header of this executable's interpreter. */ | ||
| 477 | static elf_header *interpreter_header; | ||
| 478 | |||
| 479 | /* Pointer to any PT_MIPS_ABIFLAGS program header found in the | ||
| 480 | executable itself. */ | ||
| 481 | static 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. */ | ||
| 485 | static 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 | |||
| 499 | static int | ||
| 500 | process_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 | |||
| 550 | static int | ||
| 551 | process_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 | |||
| 674 | static int | ||
| 675 | process_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 | |||
| 749 | static int | ||
| 750 | insert_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 | |||
| 936 | static char * | ||
| 937 | format_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 | |||
| 979 | char * | ||
| 980 | exec_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 | |||
| 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 (at | ||
| 10 | 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 | |||
| 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 | |||
| 38 | typedef struct | ||
| 39 | { | ||
| 40 | uint32_t word1; | ||
| 41 | uint32_t word2; | ||
| 42 | } xint64_t; | ||
| 43 | |||
| 44 | #else /* UINT64_MAX */ | ||
| 45 | typedef uint64_t xint64_t; | ||
| 46 | #endif /* !UINT64_MAX */ | ||
| 47 | |||
| 48 | |||
| 49 | |||
| 50 | /* 32-bit ELF headers. */ | ||
| 51 | |||
| 52 | struct 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 | |||
| 70 | struct 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 | |||
| 82 | struct dt_entry_32 | ||
| 83 | { | ||
| 84 | uint32_t d_tag; | ||
| 85 | uint32_t d_val; | ||
| 86 | }; | ||
| 87 | |||
| 88 | |||
| 89 | |||
| 90 | struct 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 | |||
| 108 | struct 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 | |||
| 120 | struct 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 | ||
| 131 | typedef struct elf_header_64 elf_header; | ||
| 132 | typedef struct program_header_64 program_header; | ||
| 133 | typedef struct dt_entry_64 dt_entry; | ||
| 134 | #else /* !EXEC_64 */ | ||
| 135 | typedef struct elf_header_32 elf_header; | ||
| 136 | typedef struct program_header_32 program_header; | ||
| 137 | typedef 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 | |||
| 146 | struct 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 | |||
| 172 | extern int aarch64_get_regs (pid_t, USER_REGS_STRUCT *); | ||
| 173 | extern int aarch64_set_regs (pid_t, USER_REGS_STRUCT *, bool); | ||
| 174 | |||
| 175 | #endif /* __aarch64__ */ | ||
| 176 | |||
| 177 | |||
| 178 | |||
| 179 | extern USER_WORD user_alloca (struct exec_tracee *, USER_REGS_STRUCT *, | ||
| 180 | USER_REGS_STRUCT *, USER_WORD); | ||
| 181 | extern int user_copy (struct exec_tracee *, const unsigned char *, | ||
| 182 | USER_WORD, USER_WORD); | ||
| 183 | extern void exec_init (const char *); | ||
| 184 | |||
| 185 | |||
| 186 | |||
| 187 | extern int tracing_execve (const char *, char *const *, | ||
| 188 | char *const *); | ||
| 189 | extern int after_fork (pid_t); | ||
| 190 | extern pid_t exec_waitpid (pid_t, int *, int); | ||
| 191 | |||
| 192 | |||
| 193 | |||
| 194 | /* Defined in exec.c. */ | ||
| 195 | |||
| 196 | extern 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 | |||
| 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 (at | ||
| 10 | 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 | #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 | |||
| 38 | int | ||
| 39 | main (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 | |||
| 4 | scriptversion=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 | |||
| 44 | tab=' ' | ||
| 45 | nl=' | ||
| 46 | ' | ||
| 47 | IFS=" $tab$nl" | ||
| 48 | |||
| 49 | # Set DOITPROG to "echo" to test this script. | ||
| 50 | |||
| 51 | doit=${DOITPROG-} | ||
| 52 | doit_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 | |||
| 57 | chgrpprog=${CHGRPPROG-chgrp} | ||
| 58 | chmodprog=${CHMODPROG-chmod} | ||
| 59 | chownprog=${CHOWNPROG-chown} | ||
| 60 | cmpprog=${CMPPROG-cmp} | ||
| 61 | cpprog=${CPPROG-cp} | ||
| 62 | mkdirprog=${MKDIRPROG-mkdir} | ||
| 63 | mvprog=${MVPROG-mv} | ||
| 64 | rmprog=${RMPROG-rm} | ||
| 65 | stripprog=${STRIPPROG-strip} | ||
| 66 | |||
| 67 | posix_mkdir= | ||
| 68 | |||
| 69 | # Desired mode of installed file. | ||
| 70 | mode=0755 | ||
| 71 | |||
| 72 | # Create dirs (including intermediate dirs) using mode 755. | ||
| 73 | # This is like GNU 'install' as of coreutils 8.32 (2020). | ||
| 74 | mkdir_umask=22 | ||
| 75 | |||
| 76 | backupsuffix= | ||
| 77 | chgrpcmd= | ||
| 78 | chmodcmd=$chmodprog | ||
| 79 | chowncmd= | ||
| 80 | mvcmd=$mvprog | ||
| 81 | rmcmd="$rmprog -f" | ||
| 82 | stripcmd= | ||
| 83 | |||
| 84 | src= | ||
| 85 | dst= | ||
| 86 | dir_arg= | ||
| 87 | dst_arg= | ||
| 88 | |||
| 89 | copy_on_change=false | ||
| 90 | is_target_a_directory=possibly | ||
| 91 | |||
| 92 | usage="\ | ||
| 93 | Usage: $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 | |||
| 98 | In the 1st form, copy SRCFILE to DSTFILE. | ||
| 99 | In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. | ||
| 100 | In the 4th, create DIRECTORIES. | ||
| 101 | |||
| 102 | Options: | ||
| 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 | |||
| 118 | Environment variables override the default commands: | ||
| 119 | CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG | ||
| 120 | RMPROG STRIPPROG | ||
| 121 | |||
| 122 | By default, rm is invoked with -f; when overridden with RMPROG, | ||
| 123 | it's up to you to specify -f if you want it. | ||
| 124 | |||
| 125 | If -S is not specified, no backups are attempted. | ||
| 126 | |||
| 127 | Email bug reports to bug-automake@gnu.org. | ||
| 128 | Automake home page: https://www.gnu.org/software/automake/ | ||
| 129 | " | ||
| 130 | |||
| 131 | while 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 | ||
| 184 | done | ||
| 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 | |||
| 189 | if 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 | ||
| 194 | fi | ||
| 195 | |||
| 196 | if 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 | ||
| 214 | fi | ||
| 215 | |||
| 216 | if 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 | ||
| 224 | fi | ||
| 225 | |||
| 226 | if 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 | ||
| 233 | fi | ||
| 234 | |||
| 235 | if 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 | ||
| 264 | fi | ||
| 265 | |||
| 266 | for src | ||
| 267 | do | ||
| 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 | ||
| 533 | done | ||
| 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 | |||
| 185 | timespec: | ||
| 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 | |||
| 198 | timespec: | ||
| 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 | |||
| 18 | include(`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: | ||
| 25 | dnl li $v0, 5034 # SYS_nanosleep | ||
| 26 | dnl dla $a0, .timespec # rqtp | ||
| 27 | dnl li $a1, 0 # rmtp | ||
| 28 | dnl 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 | |||
| 18 | include(`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: | ||
| 27 | dnl li $v0, SYSCALL_nanosleep # SYS_nanosleep | ||
| 28 | dnl la $a0, .timespec # rqtp | ||
| 29 | dnl li $a1, 0 # rmtp | ||
| 30 | dnl 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: | ||
| 58 | SYSCALL(`$v0',`$v1',`$zero',`$zero') # syscall args | ||
| 59 | li $v0, SYSCALL_mmap # SYS_mmap | ||
| 60 | syscall # syscall | ||
| 61 | bne $a3, $zero, .perror # perror | ||
| 62 | RESTORE() # 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 | ||
| 150 | SYSCALL(`$a2',`$a2',`$a2',`$a2') # syscall args | ||
| 151 | syscall # syscall | ||
| 152 | RESTORE() # 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 | ||
| 208 | SYSCALL(`$a2',`$a2',`$a2',`$a2') # syscall args | ||
| 209 | syscall # syscall | ||
| 210 | RESTORE() # 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 @@ | |||
| 1 | define(`CC', ` | ||
| 2 | dnl') | ||
| 3 | |||
| 4 | CC Copyright (C) 2023 Free Software Foundation, Inc. | ||
| 5 | CC | ||
| 6 | CC This file is part of GNU Emacs. | ||
| 7 | CC | ||
| 8 | CC GNU Emacs is free software: you can redistribute it and/or modify | ||
| 9 | CC it under the terms of the GNU General Public License as published | ||
| 10 | CC by the Free Software Foundation, either version 3 of the License, | ||
| 11 | CC or (at your option) any later version. | ||
| 12 | CC | ||
| 13 | CC GNU Emacs is distributed in the hope that it will be useful, but | ||
| 14 | CC WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | CC MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 16 | CC General Public License for more details. | ||
| 17 | CC | ||
| 18 | CC You should have received a copy of the GNU General Public License | ||
| 19 | CC along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 20 | |||
| 21 | .section .text | ||
| 22 | .global _start | ||
| 23 | _start: | ||
| 24 | dnl movl $162, %eax CC SYS_nanosleep | ||
| 25 | dnl leal timespec, %ebx | ||
| 26 | dnl xorl %ecx, %ecx | ||
| 27 | dnl 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 | |||
| 201 | timespec: | ||
| 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 @@ | |||
| 1 | define(`CC', ` | ||
| 2 | dnl') | ||
| 3 | |||
| 4 | CC Copyright (C) 2023 Free Software Foundation, Inc. | ||
| 5 | CC | ||
| 6 | CC This file is part of GNU Emacs. | ||
| 7 | CC | ||
| 8 | CC GNU Emacs is free software: you can redistribute it and/or modify | ||
| 9 | CC it under the terms of the GNU General Public License as published | ||
| 10 | CC by the Free Software Foundation, either version 3 of the License, | ||
| 11 | CC or (at your option) any later version. | ||
| 12 | CC | ||
| 13 | CC GNU Emacs is distributed in the hope that it will be useful, but | ||
| 14 | CC WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | CC MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 16 | CC General Public License for more details. | ||
| 17 | CC | ||
| 18 | CC You should have received a copy of the GNU General Public License | ||
| 19 | CC along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 20 | |||
| 21 | .section .text | ||
| 22 | .global _start | ||
| 23 | _start: | ||
| 24 | dnl movq $35, %rax CC SYS_nanosleep | ||
| 25 | dnl leaq timespec(%rip), %rdi | ||
| 26 | dnl xorq %rsi, %rsi | ||
| 27 | dnl 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 | |||
| 191 | error: | ||
| 192 | .ascii "_start: internal error." | ||
| 193 | timespec: | ||
| 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 | |||
| 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 (at | ||
| 10 | 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 | |||
| 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 | |||
| 36 | struct 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 | |||
| 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 (at | ||
| 10 | 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 | #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 | |||
| 68 | struct 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 | |||
| 92 | static 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 | |||
| 108 | static bool | ||
| 109 | valid_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 | |||
| 131 | static int | ||
| 132 | fp_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 | |||
| 149 | bool | ||
| 150 | cpu_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 | |||
| 171 | int | ||
| 172 | determine_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 | |||
| 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 (at | ||
| 10 | 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 | |||
| 21 | |||
| 22 | #ifndef _MIPSFPU_H_ | ||
| 23 | #define _MIPSFPU_H_ | ||
| 24 | |||
| 25 | #include "exec.h" | ||
| 26 | |||
| 27 | struct 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 | |||
| 75 | extern bool cpu_supports_fr0_p (void); | ||
| 76 | extern 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 | |||
| 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 (at | ||
| 10 | 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 | #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 | |||
| 35 | static void | ||
| 36 | print_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 | |||
| 44 | extern char **environ; | ||
| 45 | |||
| 46 | /* This program uses libexec to wrap the execution of a child | ||
| 47 | process. */ | ||
| 48 | |||
| 49 | int | ||
| 50 | main (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 | |||
| 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 (at | ||
| 10 | 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 | #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 | |||
| 77 | int | ||
| 78 | aarch64_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 | |||
| 94 | int | ||
| 95 | aarch64_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. */ | ||
| 132 | static 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 | |||
| 142 | static void | ||
| 143 | read_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 | |||
| 211 | USER_WORD | ||
| 212 | user_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 | |||
| 279 | int | ||
| 280 | user_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. */ | ||
| 349 | static struct exec_tracee *free_tracees; | ||
| 350 | |||
| 351 | /* Remove the specified TRACEE from the chain of all processes being | ||
| 352 | traced. */ | ||
| 353 | |||
| 354 | static void | ||
| 355 | remove_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. */ | ||
| 389 | static struct exec_tracee static_tracees[MAX_TRACEES]; | ||
| 390 | |||
| 391 | /* Number of tracees currently allocated. */ | ||
| 392 | static int tracees; | ||
| 393 | |||
| 394 | /* Return the `struct exec_tracee' corresponding to the specified | ||
| 395 | PROCESS. */ | ||
| 396 | |||
| 397 | static struct exec_tracee * | ||
| 398 | find_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 | |||
| 418 | static void | ||
| 419 | handle_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 | |||
| 492 | static int | ||
| 493 | handle_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. */ | ||
| 580 | static 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 | |||
| 587 | static bool | ||
| 588 | syscall_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 | |||
| 602 | static int | ||
| 603 | check_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 | |||
| 683 | static int | ||
| 684 | handle_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 | |||
| 913 | static int | ||
| 914 | handle_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 | |||
| 986 | static void | ||
| 987 | process_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, ®s); | ||
| 997 | #else /* !__aarch64__ */ | ||
| 998 | rc = ptrace (PTRACE_GETREGS, tracee->pid, NULL, | ||
| 999 | ®s); | ||
| 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, ®s); | ||
| 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, ®s, 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, ®s, 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, ®s)) | ||
| 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, ®s, false); | ||
| 1154 | #else /* !__aarch64__ */ | ||
| 1155 | ptrace (PTRACE_SETREGS, tracee->pid, NULL, ®s); | ||
| 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, ®s, false); | ||
| 1177 | #else /* !__aarch64__ */ | ||
| 1178 | ptrace (PTRACE_SETREGS, tracee->pid, NULL, ®s); | ||
| 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 | |||
| 1191 | int | ||
| 1192 | tracing_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 | |||
| 1214 | int | ||
| 1215 | after_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 | |||
| 1287 | pid_t | ||
| 1288 | exec_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 | |||
| 1428 | void | ||
| 1429 | exec_init (const char *loader) | ||
| 1430 | { | ||
| 1431 | loader_name = loader; | ||
| 1432 | } | ||