Compare commits

..

102 Commits

Author SHA1 Message Date
Dmitriy Ivanov
d717b1a3e5 Merge "Add functions to provide target sdk version" 2015-05-27 22:44:28 +00:00
Dmitriy Ivanov
79fd668bb4 Add functions to provide target sdk version
Bug: http://b/21364029
Change-Id: I8648d1bff6c8fd6e7cd12da7f128e048b9f2829a
2015-05-27 14:31:36 -07:00
Simon Baldwin
560aacee84 Merge "Fix unit tests, and extend for other architectures" 2015-05-27 16:42:38 +00:00
Simon Baldwin
1011e1a402 Fix unit tests, and extend for other architectures
On unpacking, reinstate any p_align values that packing reduced to
page size.  Ensures a round-trip pack and unpack is bit-equivalent
to the original input.
https://android-review.googlesource.com/#/c/148492/

Extend unit tests to include ia32, x64, and mips32.

Recreate test data for arm32 and arm64.  Generate new test data for
ia32, x64, and mips32.

Bug: http://b/20687795
Bug: http://b/18051137
Change-Id: Ifbca8e206ef447297ba4f19272b813702be27a35
2015-05-27 13:20:00 +01:00
Dmitriy Ivanov
fad15145f8 Merge "Remove LOCAL_CONLY_FLAGS it is no-op." 2015-05-26 20:56:37 +00:00
Dmitriy Ivanov
41c99cdbb9 Remove LOCAL_CONLY_FLAGS it is no-op.
Change-Id: Ib52b85d176dc9d46d7550f01537b2635e873d6ad
2015-05-26 11:38:59 -07:00
Dmitriy Ivanov
aaafbe128f Merge "Fix RTLD_NEXT lookup for the local_group" 2015-05-22 22:22:22 +00:00
Dmitriy Ivanov
b96ac41b32 Fix RTLD_NEXT lookup for the local_group
Linker used to skip RTLD_NEXT within local_group when
  caller->next is nullptr (which represents load order
  but not the order within local_group dependency tree)

Bug: http://b/21380474
Change-Id: I178fc4657b19bceb871635b177c1df67855b1708
2015-05-22 19:46:11 +00:00
Dan Albert
ffe01a3de6 Merge "Fix error handling for negative size in ftruncate." 2015-05-21 20:41:25 +00:00
Yabin Cui
4fc106d34b Merge "Fix pthread_attr_getstack__main_thread failure on glibc." 2015-05-20 22:52:38 +00:00
Yabin Cui
b0c6f2dba2 Fix pthread_attr_getstack__main_thread failure on glibc.
Move test of bionic specific implementation into bionic ifdef.

Bug: 19805726
Change-Id: Idf369b16e7f41f060c75b0aaf34e05cf3c161aa9
2015-05-20 14:41:15 -07:00
Dan Albert
c05554ec5c Fix error handling for negative size in ftruncate.
Bug: 21309901
Change-Id: I54692ab8105dd09db6af7a2c0894a17bdd118aa0
2015-05-20 14:20:33 -07:00
Yabin Cui
c02bdc76a2 Merge "Hide rt_sigqueueinfo." 2015-05-18 20:29:44 +00:00
Yabin Cui
40a8f214a5 Hide rt_sigqueueinfo.
Bug: 19358804
Change-Id: I38a53ad64c81d0eefdd1d24599e769fd8a477a56
2015-05-18 11:29:20 -07:00
Dmitriy Ivanov
a42b5bcd89 Merge "Apply work around b/19059885 to x86" 2015-05-16 16:56:49 +00:00
Dmitriy Ivanov
9185e04f72 Apply work around b/19059885 to x86
Bug: http://b/19059885
Bug: http://b/21203348
Change-Id: Ic375e9f877d68de8f866d17362879a7dde638465
(cherry picked from commit 69a5fb951d)
2015-05-15 18:42:14 -07:00
Elliott Hughes
882283e9e2 Merge "Don't use TEMP_FAILURE_RETRY on close in bionic." 2015-05-15 23:24:12 +00:00
Elliott Hughes
4e8ef698d0 Don't use TEMP_FAILURE_RETRY on close in bionic.
Bug: http://b/20501816
Change-Id: Id64b5109cc2b165fa0351b6edbb865a5e5058008
2015-05-15 16:20:07 -07:00
Dmitriy Ivanov
1d52b8b07c Merge "Remove -z global workaround for target x86" 2015-05-15 17:30:02 +00:00
John Reck
b00c23a8db Merge "Fix regression in crash reporting" 2015-05-15 16:29:42 +00:00
John Reck
e77e335b54 Fix regression in crash reporting
Bug: 19532651

Partial revert of be0e43b776

Change-Id: I99e220328aff985facb920ebcd84ac1a016759b5
(cherry picked from commit d7ad443cfd)
2015-05-15 09:28:10 -07:00
Dmitriy Ivanov
933332462d Remove -z global workaround for target x86
Change-Id: I08e75a1c7437c97e4af59316d2c14c7fa3f65e03
2015-05-14 21:28:21 -07:00
Elliott Hughes
0378d8f651 Merge "ScopedFd: Don't use TEMP_FAILURE_RETRY() with close()" 2015-05-14 00:27:46 +00:00
Elliott Hughes
706eafc9b0 Merge "Fix unused result errors in bionic." 2015-05-13 21:09:42 +00:00
Spencer Low
0346ad7a4f ScopedFd: Don't use TEMP_FAILURE_RETRY() with close()
According to the comments in Posix_close(), TEMP_FAILURE_RETRY() should
not be used with close():

462bdac45c%5E%21/#F12

Kill ScopedFd by simplifying the single caller.

Change-Id: I248c40b8c2fc95f1938a6edfc245c81847fc44af
Signed-off-by: Spencer Low <CompareAndSwap@gmail.com>
2015-05-13 13:27:11 -07:00
Elliott Hughes
c217373bd6 Fix unused result errors in bionic.
This lets us use _FORTIFY_SOURCE=2 on the host.

Change-Id: I69f5ff9834bfd595aae6584104bee10c4d8a5eeb
2015-05-13 13:18:04 -07:00
Dmitriy Ivanov
fe77d2d003 Merge "Improved dlsym tests and fixes to linker" 2015-05-12 20:48:17 +00:00
Dmitriy Ivanov
697bd9fd38 Improved dlsym tests and fixes to linker
Answers the question: what if dependent library
 was preloaded with RTLD_LOCAL flag.

 Also add test for RTLD_NEXT within local_group.

Bug: http://b/17512583
Change-Id: I79e081e68b3a8c0ed8980d4275a06515fea94ec9
2015-05-12 13:46:40 -07:00
Elliott Hughes
d0763ba076 Merge "Update NOTICE files (the second time today)." 2015-05-12 17:47:05 +00:00
Elliott Hughes
f58ac87182 Update NOTICE files (the second time today).
Change-Id: Ifb031d29ee697ee0682bd651e0081493e8016e67
2015-05-12 10:44:37 -07:00
Elliott Hughes
3ff027e550 Merge "Update NOTICE files." 2015-05-12 17:43:46 +00:00
Elliott Hughes
7e54c762fc Update NOTICE files.
(cherry-pick of f0bd92db8966b04062fda0986dacf80891e1a378.)
Change-Id: I4e170118abf452dd87ffe79d343ba1e2b53955de
2015-05-12 10:33:20 -07:00
Elliott Hughes
8a330cad8d Merge "Simplify three copyright headers." 2015-05-12 17:27:04 +00:00
Elliott Hughes
c69ace87ec Simplify three copyright headers.
There's no reason to have multiple years in our own copyright headers,
and given the stupidity of our NOTICE file generation, it just creates
more junk.

Change-Id: I065a3811c2e2584e3b649a18ad9460286bc72b92
2015-05-12 10:10:01 -07:00
Chih-Hung Hsieh
972d7fe63a Merge "Use unified syntax to compile with both llvm and gcc." 2015-05-12 04:31:10 +00:00
Chih-Hung Hsieh
33f33515b5 Use unified syntax to compile with both llvm and gcc.
All arch-arm and arch-arm64 .S files were compiled
by gcc with and without this patch. The output object files
were identical. When compiled with llvm and this patch,
the output files were also identical to gcc's output.

BUG: 18061004
Change-Id: I458914d512ddf5496e4eb3d288bf032cd526d32b
2015-05-11 17:15:03 -07:00
Elliott Hughes
c9310266dc Merge "Fix various bugs in the check-symbols script." 2015-05-11 20:28:57 +00:00
Elliott Hughes
ec738d9494 Fix various bugs in the check-symbols script.
It had bitrotted away during the last release cycle.

Change-Id: I20f0a3b409af4530b81f26299bef9de01530c9fd
2015-05-11 12:10:40 -07:00
Andres Morales
75f2dfca65 Merge "remove rootdir build.prop" 2015-05-08 22:13:44 +00:00
Andres Morales
4e8cda641a remove rootdir build.prop
merge with default.prop

Change-Id: I6cff4527dec2b31bdde42ec26c42ef2782f8deb4
2015-05-08 22:13:15 +00:00
Dmitriy Ivanov
267f39bf63 Merge "Switch libc/libcstdc++/libm to hash-style=both" 2015-05-08 21:07:09 +00:00
Dmitriy Ivanov
88e777d6f4 Switch libc/libcstdc++/libm to hash-style=both
Bug: http://b/19059885
Change-Id: Ie42703d91f291fd689a1cf9c35bcab5c487b9a84
2015-05-08 12:06:20 -07:00
Dan Albert
11fc3f47af Merge "Apply same URL workaround to clean build." 2015-05-08 17:15:31 +00:00
Dan Albert
a924d4ba26 Merge changes from topic 'volantis-blobs'
* changes:
  Revert "Fix volantis boot."
  Revert "Fix clang build."
  Revert "Try again to fix clang build."
2015-05-08 16:35:13 +00:00
Dmitriy Ivanov
7d6b8db28e Merge "Add definitions of Elf32_Sxword and ELFXX_R_INFO" 2015-05-08 06:49:05 +00:00
Dmitriy Ivanov
ce16a53d39 Add definitions of Elf32_Sxword and ELFXX_R_INFO
Bug: http://b/17056684
Change-Id: If35302245ac3ab40d1c80fb2b04620778c114f87
2015-05-07 23:10:16 -07:00
Yabin Cui
f9eeea6d65 Merge "Remove pthread_detach_no_leak test." 2015-05-08 01:36:30 +00:00
Yabin Cui
2957cc5f10 Remove pthread_detach_no_leak test.
This test has lost its purpose as we are using mmap/munmap for pthread_internal_t. And it is a flaky test.

Bug: 20860440
Change-Id: I7cbb6bc3fd8a2ca430415beab5ee27a856ce4ea7
2015-05-07 16:53:25 -07:00
Dan Albert
ded34ce94f Apply same URL workaround to clean build.
Change-Id: I63e63f6ffb879f49e36ee2d09821fc6fc47952c8
2015-05-07 16:33:42 -07:00
Dan Albert
7c2c01d681 Revert "Fix volantis boot."
Bug: http://b/20065774
This reverts commit 76e1cbca75.
2015-05-07 15:12:24 -07:00
Dan Albert
6f0d7005f9 Revert "Fix clang build."
Bug: http://b/20065774
This reverts commit 0975a5d9d2.
2015-05-07 15:12:16 -07:00
Dan Albert
f920f821e2 Revert "Try again to fix clang build."
Bug: http://b/20065774
This reverts commit dffd3c5838.

Change-Id: I5dd095ff4ab133baa2afcbd4c79fbee55d05c459
2015-05-07 15:11:48 -07:00
Dmitriy Ivanov
dc10b077ea Merge "Properly align init/fini_arrays for crtend.o" 2015-05-07 19:55:25 +00:00
Dmitriy Ivanov
e543c7612e Properly align init/fini_arrays for crtend.o
Also remove them from crtend_so.o

Bug: http://b/20532404
Change-Id: I56a0f80c4b3a83cf11d28bbf17791ff4ce10c5d2
2015-05-07 11:57:53 -07:00
Dmitriy Ivanov
9c1894186c Merge "Use realpath for log and error messages" 2015-05-07 17:55:39 +00:00
Dmitriy Ivanov
3edb9182ff Use realpath for log and error messages
Bug: http://b/20885931
Change-Id: Ida8ab7982ca75fa73da13c4cb10a6b2e53bc2c8e
2015-05-07 10:48:00 -07:00
Dmitriy Ivanov
fff06e624d Merge "Move pthread_atfork_dlclose test out of static lib" 2015-05-06 23:47:22 +00:00
Dmitriy Ivanov
5624a6a1e5 Move pthread_atfork_dlclose test out of static lib
Bug: http://b/20858755
Change-Id: I0d84e8b43dc33902d75af18db6b7c8e0b619d718
2015-05-06 14:15:28 -07:00
Dmitriy Ivanov
c95a9e9dad Merge "VersionTracker: Ignore libraries without soname" 2015-05-06 19:06:20 +00:00
Dmitriy Ivanov
406d99665c VersionTracker: Ignore libraries without soname
Bug: http://b/20872443
Change-Id: I7bd076885c1feae39af6ea64c9442bcc5ae5a1dc
(cherry picked from commit 8264afb377)
2015-05-06 12:04:57 -07:00
Dmitriy Ivanov
f3392791bc Merge "Fix protected symbol lookups for mips" 2015-05-05 22:39:20 +00:00
Dmitriy Ivanov
dbe26fdcc7 Fix protected symbol lookups for mips
Bug: http://b/20694161
Change-Id: I5cc58034f9776e1db9cddc34abe48ef85f6048f4
2015-05-04 19:30:49 -07:00
Dmitriy Ivanov
2c3d8d8b2c Merge "Do not adjust PT_GNU_STACK segment" 2015-05-04 19:35:51 +00:00
Dmitriy Ivanov
4637f3d66d Do not adjust PT_GNU_STACK segment
Bug: http://b/20687795
Bug: http://b/18051137
Change-Id: Ie8af3892cfbebcc0249e7981284c4ad97ff40317
(cherry picked from commit 064a9800f3)
2015-05-04 12:34:42 -07:00
Christopher Ferris
64a8698809 Modify test to avoid race condition.
automerge: 3da136a

* commit '3da136aa47e2d1608b98abb2580f024b36f92831':
  Modify test to avoid race condition.
2015-05-04 16:45:13 +00:00
Dmitriy Ivanov
7fbd6355ae Merge changes I28bd3bc4,I6860013d
* changes:
  Lookup version info when relocating mips got
  Refactoring: move VersionTracker to link_image
2015-05-01 22:43:36 +00:00
Dmitriy Ivanov
f39cb63603 Lookup version info when relocating mips got
Bug: http://b/20693971
Bug: http://b/20139821
Change-Id: I28bd3bc44dafe048761b2c598facfe20320128c4
2015-04-30 20:17:03 -07:00
Dmitriy Ivanov
7e4bbbae4a Refactoring: move VersionTracker to link_image
Use one instance of VersionTracker per link (instead of 2).

Change-Id: I6860013df65f5969975c82ebdae8bd90a82e0a82
2015-04-30 19:49:19 -07:00
Dmitriy Ivanov
788ea593ec Merge "Refactoring: extract lookup_version_info(..)" 2015-05-01 00:40:59 +00:00
Dmitriy Ivanov
31b408d2c2 Refactoring: extract lookup_version_info(..)
Change-Id: I47f9c21a1738dc520fd83281c8227dc3a7e79650
2015-04-30 16:12:32 -07:00
Mark Salyzyn
033a68f1ac Merge "bionic: fortify comments in _system_properties.h" 2015-04-30 20:57:49 +00:00
Dan Albert
6a4c9d9bf9 Merge "Define char16_t and char32_t to make gcc 5.1 happy" 2015-04-30 19:29:47 +00:00
Dmitriy Ivanov
df877d7b28 Merge "Adjust DT_MIPS_RLD_MAP2 value" 2015-04-30 05:07:40 +00:00
Dmitriy Ivanov
18c935ceab Adjust DT_MIPS_RLD_MAP2 value
DT_MIPS_RLD_MAP2 stores the difference between dynamic
  entry address and the address of the _r_debug (used by GDB)
  since the dynamic section and target address are on the
  different sides of the hole it needs to be adjusted accordingly

Bug: http://b/20658994
Bug: http://b/18051137
Change-Id: I4c5e379e8a4c68f029467df6dc660f81a7013a09
2015-04-29 19:53:31 -07:00
Dmitriy Ivanov
f29640c2d8 Merge "linker: initialize system properties" 2015-04-29 23:44:57 +00:00
Dmitriy Ivanov
c6b9b254dc Merge "Fix mips relocation to use load_bias as intended" 2015-04-29 21:58:57 +00:00
Dmitriy Ivanov
0373d4f473 Fix mips relocation to use load_bias as intended
Bug: http://b/20658994
Change-Id: I5a15605fe34db359e26d563e13841ae993083c4a
2015-04-29 14:41:06 -07:00
Mark Salyzyn
c3f4c964a3 bionic: fortify comments in _system_properties.h
Change-Id: I2ef8fb7ae5ae03d5d2a50b5a417d585710099760
2015-04-29 13:57:42 -07:00
Neil Fuller
fa6f649607 Merge "Update to tzdata 2015d" 2015-04-29 10:42:16 +00:00
Dmitriy Ivanov
e1a61f5e93 Merge "Fix LD_PRELOAD for dlopen()" 2015-04-29 01:59:53 +00:00
Jeff Brown
0bf650373e Merge "Add float support to binary event log." 2015-04-29 01:42:49 +00:00
Jeff Brown
11331f60dd Add float support to binary event log.
Bug: 20664753
Change-Id: I6e43c07daa727c19d87f5192bb719af63dd93654
2015-04-28 18:20:22 -07:00
Dmitriy Ivanov
f8093a9485 Fix LD_PRELOAD for dlopen()
We did not set DF_1_GLOBAL flag for LD_PRELOADed
 libraries which led to the situation when ld_preloads
 where ignored during on dlopen()

Change-Id: I696b3b2506a8ed4c0984ad2c803210a7a4f8e686
2015-04-28 18:09:53 -07:00
Dmitriy Ivanov
b4e5067cab linker: initialize system properties
Bug: http://b/20567629
Bug: https://code.google.com/p/chromium/issues/detail?id=478886
Change-Id: I8d2d89b749015e7fcd6e7ea646911f2e617dd1ba
2015-04-28 15:52:52 -07:00
Mark Salyzyn
b904afa16e Merge "bionic: add __system_property_area_serial()" 2015-04-28 22:11:52 +00:00
Dmitriy Ivanov
9f0d99d298 Merge "Do not pack relocations for libc.so" 2015-04-28 22:06:43 +00:00
Dmitriy Ivanov
62d6533c1a Do not pack relocations for libc.so
Bug: http://b/20645321
Bug: http://b/20655855
(cherry picked from commit 452742d2bf)

Change-Id: Ic9125cc1bc4c9ba9eb20d030de72e3ce1fb86fa6
2015-04-28 15:05:20 -07:00
Dmitriy Ivanov
bed7a7e5eb Merge "linker: use libc's environ variable to store envp" 2015-04-28 21:35:59 +00:00
Dmitriy Ivanov
a85bcc2e99 linker: use libc's environ variable to store envp
This is to make getenv() work correctly.

Bug: http://b/20567629
Change-Id: I148627e1efea1649fb0822c95876811652fb4082
2015-04-28 14:21:36 -07:00
Christopher Ferris
6fa65e7cd5 Merge "cortex-a9: Fix reference to __memcpy_base_aligned." 2015-04-28 20:28:42 +00:00
Kyle Repinski
e0905c94d3 cortex-a9: Fix reference to __memcpy_base_aligned.
With a different memcpy, __memcpy_base_aligned ceased to exist.
Instead, point to the name defined by whatever includes memcpy_base.S

Change-Id: I242cf49cbada35337ba155d7f170e86a905ff55f
2015-04-28 14:29:15 -05:00
Neil Fuller
520cbf51b1 Update to tzdata 2015d
Changes affecting future time stamps

    Egypt will not observe DST in 2015 and will consider canceling it
    permanently.  For now, assume no DST indefinitely.
    (Thanks to Ahmed Nazmy and Tim Parenti.)

  Changes affecting past time stamps

    America/Whitehorse switched from UTC-9 to UTC-8 on 1967-05-28, not
    1966-07-01.  Also, Yukon's time zone history is documented better.
    (Thanks to Brian Inglis and Dennis Ferguson.)

  Change affecting past and future time zone abbreviations

    The abbreviations for Hawaii-Aleutian standard and daylight times
    have been changed from HAST/HADT to HST/HDT, as per US Government
    Printing Office style.  This affects only America/Adak since 1983,
    as America/Honolulu was already using the new style.

Bug: 20551453
Change-Id: I02364f15ca4ae20ed1a3b327f8517214bee938e5
2015-04-28 17:11:03 +01:00
Dmitriy Ivanov
42d7468f99 Merge "Reduce p_align for program header to page size." 2015-04-28 03:38:27 +00:00
Dmitriy Ivanov
b293969c6d Reduce p_align for program header to page size.
Having p_align > page_size leads to the situation when striping
 packed executables results in unnecessary p_vaddr adjustments.
 And it also may result (with probability 1 - 1/sizeof(uintptr_t)) in
 misaligned segments following .dynstr

Bug: http://b/20629834
Bug: http://b/18051137
Change-Id: I1c5da4911e4409d63cb09f6b6b0a16ef54f6501b
2015-04-27 20:37:17 -07:00
Dmitriy Ivanov
032907d8c7 Merge "Remove outdated warning" 2015-04-27 18:28:31 +00:00
Dmitriy Ivanov
2ea504fed1 Remove outdated warning
It is ok to use malloc in linker.

Bug: http://b/20567629
Change-Id: I54183dbe8ebcd223a44e710e511c339688a65dba
2015-04-27 11:24:36 -07:00
Chih-Hung Hsieh
59bce688c7 Merge "Fix opcode to compile with both gcc and llvm." 2015-04-27 17:17:45 +00:00
Mark Salyzyn
bfd65279a5 bionic: add __system_property_area_serial()
Adds a new _internal_ function. Provide a global serial number to
support more efficient private caching algorithms. This allows
to skip re-running the __system_property_find() call on misses until
there is a global change in the properties. This call is a read
barrier, the property data to be read following this call will be
read sequentially and up to date.

Bug: 19544788
Change-Id: I58e6a92baa0f3e8e7b9ec79b10af6d56407dab48
2015-04-27 07:44:03 -07:00
Neil Fuller
682a240c5d Merge "Update to tzdata 2015c" 2015-04-27 08:19:16 +00:00
Bernhard Rosenkränzer
6f88821e5d Define char16_t and char32_t to make gcc 5.1 happy
gcc 5.1 doesn't define char16_t and char32_t (unless in C++ mode),
causing compile failures.

Change-Id: I08dcd13cdf8cd59a4a2f191864bedf4c0d1bb313
Signed-off-by: Bernhard Rosenkränzer <Bernhard.Rosenkranzer@linaro.org>
2015-04-24 16:21:38 +02:00
Neil Fuller
d2177404e2 Update to tzdata 2015c
Changes affecting future time stamps

    Egypt's spring-forward transition is at 24:00 on April's last Thursday,
    not 00:00 on April's last Friday.  2015's transition will therefore be on
    Thursday, April 30 at 24:00, not Friday, April 24 at 00:00.  Similar fixes
    apply to 2026, 2037, 2043, etc.  (Thanks to Steffen Thorsen.)

  Changes affecting past time stamps

    The following changes affect some pre-1991 Chile-related time stamps
    in America/Santiago, Antarctica/Palmer, and Pacific/Easter.

      The 1910 transition was January 10, not January 1.

      The 1918 transition was September 10, not September 1.

      The UTC-4 time observed from 1932 to 1942 is now considered to be
      standard time, not year-round DST.

      Santiago observed DST (UTC-3) from 1946-07-15 through 1946-08-31,
      then reverted to standard time, then switched its time zone to
      UTC-5 on 1947-04-01.

      Assume transitions before 1968 were at 00:00, since we have no data
      saying otherwise.

      The spring 1988 transition was 1988-10-09, not 1988-10-02.
      The fall 1990 transition was 1990-03-11, not 1990-03-18.

      Assume no UTC offset change for Pacific/Easter on 1890-01-01,
      and omit all transitions on Pacific/Easter from 1942 through 1946
      since we have no data suggesting that they existed.

    One more zone has been turned into a link, as it differed
    from an existing zone only for older time stamps.  As usual,
    this change affects UTC offsets in pre-1970 time stamps only.
    The zone's old contents have been moved to the 'backzone' file.
    The affected zone is America/Montreal.

Bug: 20287125
Change-Id: I8512c4e9ab09725395b256aba59ca34a23d1c995
2015-04-24 13:56:11 +01:00
Chih-Hung Hsieh
0a93df369c Fix opcode to compile with both gcc and llvm.
BUG: 17302991

Change-Id: I31febd9ad24312388068803ce247b295bd73b607
2015-04-23 21:40:31 +00:00
120 changed files with 2501 additions and 4837 deletions

View File

@@ -16,6 +16,7 @@
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <benchmark/Benchmark.h>
@@ -73,7 +74,7 @@ static void FopenFgetsFclose(int iters, bool no_locking) {
for (int i = 0; i < iters; ++i) {
FILE* fp = fopen("/proc/version", "re");
if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
fgets(buf, sizeof(buf), fp);
if (fgets(buf, sizeof(buf), fp) == nullptr) abort();
fclose(fp);
}
}

View File

@@ -14,6 +14,8 @@
* limitations under the License.
*/
#include "utils.h"
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
@@ -21,7 +23,7 @@
#include <string>
#include "utils.h"
#include <base/stringprintf.h>
int Round(int n) {
int base = 1;
@@ -72,10 +74,7 @@ std::string PrettyInt(long value, size_t base) {
break;
}
}
char* s = NULL;
asprintf(&s, "%s%" PRId64 "%s", (negative_number ? "-" : ""),
count / kAmountPerUnit[i], kUnitStrings[i]);
std::string result(s);
free(s);
return result;
return android::base::StringPrintf("%s%" PRId64 "%s",
negative_number ? "-" : "",
count / kAmountPerUnit[i], kUnitStrings[i]);
}

View File

@@ -129,10 +129,8 @@ libc_bionic_ndk_src_files := \
bionic/fchmod.cpp \
bionic/fchmodat.cpp \
bionic/ffs.cpp \
bionic/fgetxattr.cpp \
bionic/flockfile.cpp \
bionic/fpclassify.cpp \
bionic/fsetxattr.cpp \
bionic/ftruncate.cpp \
bionic/futimens.cpp \
bionic/getcwd.cpp \
@@ -549,16 +547,14 @@ libc_thread_atexit_impl_src_files := \
libc_arch_static_src_files := \
bionic/dl_iterate_phdr_static.cpp \
# Various kinds of cruft.
# Various kinds of LP32 cruft.
# ========================================================
libc_common_src_files += \
bionic/ndk_cruft.cpp \
libc_bionic_ndk_src_files_32 += \
libc_bionic_src_files_32 += \
bionic/mmap.cpp \
libc_common_src_files_32 += \
bionic/legacy_32_bit_support.cpp \
bionic/ndk_cruft.cpp \
bionic/time64.c \
libc_netbsd_src_files_32 += \
@@ -958,7 +954,6 @@ LOCAL_ADDRESS_SANITIZER := false
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_bionic_src_files))
include $(BUILD_STATIC_LIBRARY)
@@ -986,7 +981,7 @@ LOCAL_ADDRESS_SANITIZER := false
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_bionic_ndk_src_files))
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_bionic_src_files))
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
@@ -1340,7 +1335,7 @@ LOCAL_CLANG := $(use_clang)
LOCAL_REQUIRED_MODULES := tzdata
LOCAL_ADDITIONAL_DEPENDENCIES := \
$(libc_common_additional_dependencies) \
$(LOCAL_PATH)/libc.map \
$(LOCAL_PATH)/version_script.txt \
# Leave the symbols in the shared library so that stack unwinders can produce
# meaningful name resolution.
@@ -1368,7 +1363,7 @@ LOCAL_CXX_STL := none
LOCAL_SYSTEM_SHARED_LIBRARIES :=
# Don't re-export new/delete and friends, even if the compiler really wants to.
LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/libc.map
LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/version_script.txt
# We'd really like to do this for all architectures, but since this wasn't done
# before, these symbols must continue to be exported on LP32 for binary

View File

@@ -122,8 +122,8 @@ int fdatasync(int) all
int fchown:fchown32(int, uid_t, gid_t) arm,x86
int fchown:fchown(int, uid_t, gid_t) arm64,mips,mips64,x86_64
void sync(void) all
int ___fsetxattr:fsetxattr(int, const char*, const void*, size_t, int) all
ssize_t ___fgetxattr:fgetxattr(int, const char*, void*, size_t) all
int fsetxattr(int, const char*, const void*, size_t, int) all
ssize_t fgetxattr(int, const char*, void*, size_t) all
ssize_t flistxattr(int, char*, size_t) all
int fremovexattr(int, const char*) all
@@ -203,7 +203,7 @@ clock_t times(struct tms*) all
int nanosleep(const struct timespec*, struct timespec*) all
int clock_settime(clockid_t, const struct timespec*) all
int clock_getres(clockid_t, struct timespec*) all
int ___clock_nanosleep:clock_nanosleep(clockid_t, int, const struct timespec*, struct timespec*) all
int __clock_nanosleep:clock_nanosleep(clockid_t, int, const struct timespec*, struct timespec*) all
int getitimer(int, const struct itimerval*) all
int setitimer(int, const struct itimerval*, struct itimerval*) all
int __timer_create:timer_create(clockid_t clockid, struct sigevent* evp, __kernel_timer_t* timerid) all
@@ -308,9 +308,6 @@ int inotify_rm_watch(int, unsigned int) all
int __pselect6:pselect6(int, fd_set*, fd_set*, fd_set*, timespec*, void*) all
int __ppoll:ppoll(pollfd*, unsigned int, timespec*, const sigset_t*, size_t) all
ssize_t process_vm_readv(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long) all
ssize_t process_vm_writev(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long) all
int __set_tid_address:set_tid_address(int*) all
int setfsgid(gid_t) all

View File

@@ -39,6 +39,7 @@ libc_bionic_src_files_arm += \
arch-arm/bionic/__bionic_clone.S \
arch-arm/bionic/_exit_with_stack_teardown.S \
arch-arm/bionic/libgcc_compat.c \
arch-arm/bionic/libgcc_protect_unwind.c \
arch-arm/bionic/__restore.S \
arch-arm/bionic/setjmp.S \
arch-arm/bionic/syscall.S \

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// TODO: This file should go away once unwinder migration to libc++.so is complete.
extern char _Unwind_Backtrace __attribute((visibility("protected")));
extern char __gnu_Unwind_Find_exidx __attribute((visibility("protected")));
extern char __gnu_Unwind_Restore_VFP_D __attribute((visibility("protected")));
extern char __gnu_Unwind_Restore_VFP __attribute((visibility("protected")));
extern char __gnu_Unwind_Restore_VFP_D_16_to_31 __attribute((visibility("protected")));
extern char __gnu_Unwind_Restore_WMMXD __attribute((visibility("protected")));
extern char __gnu_Unwind_Restore_WMMXC __attribute((visibility("protected")));
extern char _Unwind_GetCFA __attribute((visibility("protected")));
extern char __gnu_Unwind_RaiseException __attribute((visibility("protected")));
extern char __gnu_Unwind_ForcedUnwind __attribute((visibility("protected")));
extern char __gnu_Unwind_Resume __attribute((visibility("protected")));
extern char __gnu_Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
extern char _Unwind_Complete __attribute((visibility("protected")));
extern char _Unwind_DeleteException __attribute((visibility("protected")));
extern char _Unwind_VRS_Get __attribute((visibility("protected")));
extern char _Unwind_VRS_Set __attribute((visibility("protected")));
extern char __gnu_Unwind_Backtrace __attribute((visibility("protected")));
extern char _Unwind_VRS_Pop __attribute((visibility("protected")));
extern char __gnu_Unwind_Save_VFP_D __attribute((visibility("protected")));
extern char __gnu_Unwind_Save_VFP __attribute((visibility("protected")));
extern char __gnu_Unwind_Save_VFP_D_16_to_31 __attribute((visibility("protected")));
extern char __gnu_Unwind_Save_WMMXD __attribute((visibility("protected")));
extern char __gnu_Unwind_Save_WMMXC __attribute((visibility("protected")));
extern char ___Unwind_RaiseException __attribute((visibility("protected")));
extern char _Unwind_RaiseException __attribute((visibility("protected")));
extern char ___Unwind_Resume __attribute((visibility("protected")));
extern char _Unwind_Resume __attribute((visibility("protected")));
extern char ___Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
extern char _Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
extern char ___Unwind_ForcedUnwind __attribute((visibility("protected")));
extern char _Unwind_ForcedUnwind __attribute((visibility("protected")));
extern char ___Unwind_Backtrace __attribute((visibility("protected")));
extern char _Unwind_GetRegionStart __attribute((visibility("protected")));
extern char _Unwind_GetLanguageSpecificData __attribute((visibility("protected")));
extern char _Unwind_GetDataRelBase __attribute((visibility("protected")));
extern char _Unwind_GetTextRelBase __attribute((visibility("protected")));
void* __bionic_libgcc_unwind_symbols[] = {
&_Unwind_Backtrace,
&__gnu_Unwind_Find_exidx,
&__gnu_Unwind_Restore_VFP_D,
&__gnu_Unwind_Restore_VFP,
&__gnu_Unwind_Restore_VFP_D_16_to_31,
&__gnu_Unwind_Restore_WMMXD,
&__gnu_Unwind_Restore_WMMXC,
&_Unwind_GetCFA,
&__gnu_Unwind_RaiseException,
&__gnu_Unwind_ForcedUnwind,
&__gnu_Unwind_Resume,
&__gnu_Unwind_Resume_or_Rethrow,
&_Unwind_Complete,
&_Unwind_DeleteException,
&_Unwind_VRS_Get,
&_Unwind_VRS_Set,
&__gnu_Unwind_Backtrace,
&_Unwind_VRS_Pop,
&__gnu_Unwind_Save_VFP_D,
&__gnu_Unwind_Save_VFP,
&__gnu_Unwind_Save_VFP_D_16_to_31,
&__gnu_Unwind_Save_WMMXD,
&__gnu_Unwind_Save_WMMXC,
&___Unwind_RaiseException,
&_Unwind_RaiseException,
&___Unwind_Resume,
&_Unwind_Resume,
&___Unwind_Resume_or_Rethrow,
&_Unwind_Resume_or_Rethrow,
&___Unwind_ForcedUnwind,
&_Unwind_ForcedUnwind,
&___Unwind_Backtrace,
&_Unwind_GetRegionStart,
&_Unwind_GetLanguageSpecificData,
&_Unwind_GetDataRelBase,
&_Unwind_GetTextRelBase,
};

View File

@@ -1 +0,0 @@
include bionic/libc/arch-arm/cortex-a7/cortex-a7.mk

View File

@@ -44,7 +44,7 @@ ENTRY_PRIVATE(MEMCPY_BASE)
/* check if buffers are aligned. If so, run arm-only version */
eor r3, r0, r1
ands r3, r3, #0x3
beq __memcpy_base_aligned
beq MEMCPY_BASE_ALIGNED
/* Check the upper size limit for Neon unaligned memory access in memcpy */
cmp r2, #224

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___clock_nanosleep)
ENTRY(__clock_nanosleep)
mov ip, r7
ldr r7, =__NR_clock_nanosleep
swi #0
@@ -11,5 +11,4 @@ ENTRY(___clock_nanosleep)
bxls lr
neg r0, r0
b __set_errno_internal
END(___clock_nanosleep)
.hidden ___clock_nanosleep
END(__clock_nanosleep)

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___fgetxattr)
ENTRY(fgetxattr)
mov ip, r7
ldr r7, =__NR_fgetxattr
swi #0
@@ -11,5 +11,4 @@ ENTRY(___fgetxattr)
bxls lr
neg r0, r0
b __set_errno_internal
END(___fgetxattr)
.hidden ___fgetxattr
END(fgetxattr)

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___fsetxattr)
ENTRY(fsetxattr)
mov ip, sp
stmfd sp!, {r4, r5, r6, r7}
.cfi_def_cfa_offset 16
@@ -19,5 +19,4 @@ ENTRY(___fsetxattr)
bxls lr
neg r0, r0
b __set_errno_internal
END(___fsetxattr)
.hidden ___fsetxattr
END(fsetxattr)

View File

@@ -1,22 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(process_vm_readv)
mov ip, sp
stmfd sp!, {r4, r5, r6, r7}
.cfi_def_cfa_offset 16
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
.cfi_rel_offset r6, 8
.cfi_rel_offset r7, 12
ldmfd ip, {r4, r5, r6}
ldr r7, =__NR_process_vm_readv
swi #0
ldmfd sp!, {r4, r5, r6, r7}
.cfi_def_cfa_offset 0
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno_internal
END(process_vm_readv)

View File

@@ -1,22 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(process_vm_writev)
mov ip, sp
stmfd sp!, {r4, r5, r6, r7}
.cfi_def_cfa_offset 16
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
.cfi_rel_offset r6, 8
.cfi_rel_offset r7, 12
ldmfd ip, {r4, r5, r6}
ldr r7, =__NR_process_vm_writev
swi #0
ldmfd sp!, {r4, r5, r6, r7}
.cfi_def_cfa_offset 0
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno_internal
END(process_vm_writev)

View File

@@ -1 +0,0 @@
include bionic/libc/arch-arm64/generic/generic.mk

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___clock_nanosleep)
ENTRY(__clock_nanosleep)
mov x8, __NR_clock_nanosleep
svc #0
@@ -11,5 +11,5 @@ ENTRY(___clock_nanosleep)
b.hi __set_errno_internal
ret
END(___clock_nanosleep)
.hidden ___clock_nanosleep
END(__clock_nanosleep)
.hidden __clock_nanosleep

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___fgetxattr)
ENTRY(fgetxattr)
mov x8, __NR_fgetxattr
svc #0
@@ -11,5 +11,4 @@ ENTRY(___fgetxattr)
b.hi __set_errno_internal
ret
END(___fgetxattr)
.hidden ___fgetxattr
END(fgetxattr)

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___fsetxattr)
ENTRY(fsetxattr)
mov x8, __NR_fsetxattr
svc #0
@@ -11,5 +11,4 @@ ENTRY(___fsetxattr)
b.hi __set_errno_internal
ret
END(___fsetxattr)
.hidden ___fsetxattr
END(fsetxattr)

View File

@@ -1,14 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(process_vm_readv)
mov x8, __NR_process_vm_readv
svc #0
cmn x0, #(MAX_ERRNO + 1)
cneg x0, x0, hi
b.hi __set_errno_internal
ret
END(process_vm_readv)

View File

@@ -1,14 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(process_vm_writev)
mov x8, __NR_process_vm_writev
svc #0
cmn x0, #(MAX_ERRNO + 1)
cneg x0, x0, hi
b.hi __set_errno_internal
ret
END(process_vm_writev)

View File

@@ -6,9 +6,6 @@
libc_bionic_src_files_mips += \
arch-mips/string/memcmp.c \
arch-mips/string/memcpy.S \
arch-mips/string/memset.S \
arch-mips/string/strcmp.S \
bionic/__memcpy_chk.cpp \
bionic/__memset_chk.cpp \
bionic/__strcpy_chk.cpp \
@@ -34,6 +31,7 @@ libc_openbsd_src_files_mips += \
upstream-openbsd/lib/libc/string/stpcpy.c \
upstream-openbsd/lib/libc/string/stpncpy.c \
upstream-openbsd/lib/libc/string/strcat.c \
upstream-openbsd/lib/libc/string/strcmp.c \
upstream-openbsd/lib/libc/string/strcpy.c \
upstream-openbsd/lib/libc/string/strlcat.c \
upstream-openbsd/lib/libc/string/strlcpy.c \
@@ -56,10 +54,14 @@ libc_bionic_src_files_mips += \
ifndef ARCH_MIPS_REV6
libc_bionic_src_files_mips += \
arch-mips/string/memcpy.S \
arch-mips/string/memset.S \
arch-mips/string/mips_strlen.c \
else
libc_bionic_src_files_mips += \
arch-mips/string/memcpy.c \
arch-mips/string/memset.c \
arch-mips/string/strlen.c \
endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,91 @@
/* $OpenBSD: memcpy.c,v 1.1 2014/11/30 19:43:56 deraadt Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
/*
* sizeof(word) MUST BE A POWER OF TWO
* SO THAT wmask BELOW IS ALL ONES
*/
typedef long word; /* "word" used for optimal copy speed */
#define wsize sizeof(word)
#define wmask (wsize - 1)
/*
* Copy a block of memory, not handling overlap.
*/
void *
memcpy(void *dst0, const void *src0, size_t length)
{
char *dst = dst0;
const char *src = src0;
size_t t;
if (length == 0 || dst == src) /* nothing to do */
goto done;
/*
* Macros: loop-t-times; and loop-t-times, t>0
*/
#define TLOOP(s) if (t) TLOOP1(s)
#define TLOOP1(s) do { s; } while (--t)
/*
* Copy forward.
*/
t = (long)src; /* only need low bits */
if ((t | (long)dst) & wmask) {
/*
* Try to align operands. This cannot be done
* unless the low bits match.
*/
if ((t ^ (long)dst) & wmask || length < wsize)
t = length;
else
t = wsize - (t & wmask);
length -= t;
TLOOP1(*dst++ = *src++);
}
/*
* Copy whole words, then mop up any trailing bytes.
*/
t = length / wsize;
TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
t = length & wmask;
TLOOP(*dst++ = *src++);
done:
return (dst0);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013
* Copyright (c) 2009
* MIPS Technologies, Inc., California.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,410 +27,216 @@
* SUCH DAMAGE.
*/
#ifdef __ANDROID__
# include <private/bionic_asm.h>
# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
#elif _LIBC
# include <sysdep.h>
# include <regdef.h>
# include <sys/asm.h>
# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
#elif _COMPILING_NEWLIB
# include "machine/asm.h"
# include "machine/regdef.h"
# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
/************************************************************************
*
* memset.S, version "64h" with 1 cache line horizon for "pref 30" and 14 nops
* Version: "043009"
*
************************************************************************/
/************************************************************************
* Include files
************************************************************************/
#include <private/bionic_asm.h>
/*
* This routine could be optimized for MIPS64. The current code only
* uses MIPS32 instructions.
*/
#if defined(__MIPSEB__)
# define SWHI swl /* high part is left in big-endian */
# define SWLO swr /* low part is right in big-endian */
#endif
#if defined(__MIPSEL__)
# define SWHI swr /* high part is right in little-endian */
# define SWLO swl /* low part is left in little-endian */
#endif
#if !(defined(XGPROF) || defined(XPROF))
#undef SETUP_GP
#define SETUP_GP
#endif
#ifdef NDEBUG
#define DBG #
#else
# include <regdef.h>
# include <sys/asm.h>
#define DBG
#endif
/* Check to see if the MIPS architecture we are compiling for supports
prefetching. */
LEAF(memset,0)
#if (__mips == 4) || (__mips == 5) || (__mips == 32) || (__mips == 64)
# ifndef DISABLE_PREFETCH
# define USE_PREFETCH
# endif
#endif
#if defined(_MIPS_SIM) && ((_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32))
# ifndef DISABLE_DOUBLE
# define USE_DOUBLE
# endif
#endif
#ifndef USE_DOUBLE
# ifndef DISABLE_DOUBLE_ALIGN
# define DOUBLE_ALIGN
# endif
#endif
/* Some asm.h files do not have the L macro definition. */
#ifndef L
# if _MIPS_SIM == _ABIO32
# define L(label) $L ## label
# else
# define L(label) .L ## label
# endif
#endif
/* Some asm.h files do not have the PTR_ADDIU macro definition. */
#ifndef PTR_ADDIU
# if _MIPS_SIM == _ABIO32
# define PTR_ADDIU addiu
# else
# define PTR_ADDIU daddiu
# endif
#endif
/* New R6 instructions that may not be in asm.h. */
#ifndef PTR_LSA
# if _MIPS_SIM == _ABIO32
# define PTR_LSA lsa
# else
# define PTR_LSA dlsa
# endif
#endif
/* Using PREFETCH_HINT_PREPAREFORSTORE instead of PREFETCH_STORE
or PREFETCH_STORE_STREAMED offers a large performance advantage
but PREPAREFORSTORE has some special restrictions to consider.
Prefetch with the 'prepare for store' hint does not copy a memory
location into the cache, it just allocates a cache line and zeros
it out. This means that if you do not write to the entire cache
line before writing it out to memory some data will get zero'ed out
when the cache line is written back to memory and data will be lost.
There are ifdef'ed sections of this memcpy to make sure that it does not
do prefetches on cache lines that are not going to be completely written.
This code is only needed and only used when PREFETCH_STORE_HINT is set to
PREFETCH_HINT_PREPAREFORSTORE. This code assumes that cache lines are
less than MAX_PREFETCH_SIZE bytes and if the cache line is larger it will
not work correctly. */
#ifdef USE_PREFETCH
# define PREFETCH_HINT_STORE 1
# define PREFETCH_HINT_STORE_STREAMED 5
# define PREFETCH_HINT_STORE_RETAINED 7
# define PREFETCH_HINT_PREPAREFORSTORE 30
/* If we have not picked out what hints to use at this point use the
standard load and store prefetch hints. */
# ifndef PREFETCH_STORE_HINT
# define PREFETCH_STORE_HINT PREFETCH_HINT_STORE
# endif
/* We double everything when USE_DOUBLE is true so we do 2 prefetches to
get 64 bytes in that case. The assumption is that each individual
prefetch brings in 32 bytes. */
# ifdef USE_DOUBLE
# define PREFETCH_CHUNK 64
# define PREFETCH_FOR_STORE(chunk, reg) \
pref PREFETCH_STORE_HINT, (chunk)*64(reg); \
pref PREFETCH_STORE_HINT, ((chunk)*64)+32(reg)
# else
# define PREFETCH_CHUNK 32
# define PREFETCH_FOR_STORE(chunk, reg) \
pref PREFETCH_STORE_HINT, (chunk)*32(reg)
# endif
/* MAX_PREFETCH_SIZE is the maximum size of a prefetch, it must not be less
than PREFETCH_CHUNK, the assumed size of each prefetch. If the real size
of a prefetch is greater than MAX_PREFETCH_SIZE and the PREPAREFORSTORE
hint is used, the code will not work correctly. If PREPAREFORSTORE is not
used than MAX_PREFETCH_SIZE does not matter. */
# define MAX_PREFETCH_SIZE 128
/* PREFETCH_LIMIT is set based on the fact that we never use an offset greater
than 5 on a STORE prefetch and that a single prefetch can never be larger
than MAX_PREFETCH_SIZE. We add the extra 32 when USE_DOUBLE is set because
we actually do two prefetches in that case, one 32 bytes after the other. */
# ifdef USE_DOUBLE
# define PREFETCH_LIMIT (5 * PREFETCH_CHUNK) + 32 + MAX_PREFETCH_SIZE
# else
# define PREFETCH_LIMIT (5 * PREFETCH_CHUNK) + MAX_PREFETCH_SIZE
# endif
# if (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE) \
&& ((PREFETCH_CHUNK * 4) < MAX_PREFETCH_SIZE)
/* We cannot handle this because the initial prefetches may fetch bytes that
are before the buffer being copied. We start copies with an offset
of 4 so avoid this situation when using PREPAREFORSTORE. */
# error "PREFETCH_CHUNK is too large and/or MAX_PREFETCH_SIZE is too small."
# endif
#else /* USE_PREFETCH not defined */
# define PREFETCH_FOR_STORE(offset, reg)
#endif
#if __mips_isa_rev > 5
# if (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
# undef PREFETCH_STORE_HINT
# define PREFETCH_STORE_HINT PREFETCH_HINT_STORE_STREAMED
# endif
# define R6_CODE
#endif
/* Allow the routine to be named something else if desired. */
#ifndef MEMSET_NAME
# define MEMSET_NAME memset
#endif
/* We load/store 64 bits at a time when USE_DOUBLE is true.
The C_ prefix stands for CHUNK and is used to avoid macro name
conflicts with system header files. */
#ifdef USE_DOUBLE
# define C_ST sd
# if __MIPSEB
# define C_STHI sdl /* high part is left in big-endian */
# else
# define C_STHI sdr /* high part is right in little-endian */
# endif
#else
# define C_ST sw
# if __MIPSEB
# define C_STHI swl /* high part is left in big-endian */
# else
# define C_STHI swr /* high part is right in little-endian */
# endif
#endif
/* Bookkeeping values for 32 vs. 64 bit mode. */
#ifdef USE_DOUBLE
# define NSIZE 8
# define NSIZEMASK 0x3f
# define NSIZEDMASK 0x7f
#else
# define NSIZE 4
# define NSIZEMASK 0x1f
# define NSIZEDMASK 0x3f
#endif
#define UNIT(unit) ((unit)*NSIZE)
#define UNITM1(unit) (((unit)*NSIZE)-1)
#ifdef __ANDROID__
LEAF(MEMSET_NAME,0)
#else
LEAF(MEMSET_NAME)
#endif
.set nomips16
.set noreorder
/* If the size is less than 2*NSIZE (8 or 16), go to L(lastb). Regardless of
size, copy dst pointer to v0 for the return value. */
slti t2,a2,(2 * NSIZE)
bne t2,zero,L(lastb)
move v0,a0
.set noat
/* If memset value is not zero, we copy it to all the bytes in a 32 or 64
bit word. */
beq a1,zero,L(set0) /* If memset value is zero no smear */
PTR_SUBU a3,zero,a0
nop
addu t0,a0,a2 # t0 is the "past the end" address
slti AT,a2,4 # is a2 less than 4?
bne AT,zero,.Llast4 # if yes, go to last4
move v0,a0 # memset returns the dst pointer
/* smear byte into 32 or 64 bit word */
#if ((__mips == 64) || (__mips == 32)) && (__mips_isa_rev >= 2)
# ifdef USE_DOUBLE
dins a1, a1, 8, 8 /* Replicate fill byte into half-word. */
dins a1, a1, 16, 16 /* Replicate fill byte into word. */
dins a1, a1, 32, 32 /* Replicate fill byte into dbl word. */
# else
ins a1, a1, 8, 8 /* Replicate fill byte into half-word. */
ins a1, a1, 16, 16 /* Replicate fill byte into word. */
# endif
beq a1,zero,.Lset0
subu v1,zero,a0
# smear byte into 32 bit word
#if (__mips==32) && (__mips_isa_rev>=2)
ins a1, a1, 8, 8 # Replicate fill byte into half-word.
ins a1, a1, 16, 16 # Replicate fill byte into word.
#else
# ifdef USE_DOUBLE
and a1,0xff
dsll t2,a1,8
or a1,t2
dsll t2,a1,16
or a1,t2
dsll t2,a1,32
or a1,t2
# else
and a1,0xff
sll t2,a1,8
or a1,t2
sll t2,a1,16
or a1,t2
# endif
and a1,0xff
sll AT,a1,8
or a1,AT
sll AT,a1,16
or a1,AT
#endif
/* If the destination address is not aligned do a partial store to get it
aligned. If it is already aligned just jump to L(aligned). */
L(set0):
#ifndef R6_CODE
andi t2,a3,(NSIZE-1) /* word-unaligned address? */
beq t2,zero,L(aligned) /* t2 is the unalignment count */
PTR_SUBU a2,a2,t2
C_STHI a1,0(a0)
PTR_ADDU a0,a0,t2
#else /* R6_CODE */
andi t2,a0,(NSIZE-1)
lapc t9,L(atable)
PTR_LSA t9,t2,t9,2
jrc t9
L(atable):
bc L(aligned)
# ifdef USE_DOUBLE
bc L(lb7)
bc L(lb6)
bc L(lb5)
bc L(lb4)
# endif
bc L(lb3)
bc L(lb2)
bc L(lb1)
L(lb7):
sb a1,6(a0)
L(lb6):
sb a1,5(a0)
L(lb5):
sb a1,4(a0)
L(lb4):
sb a1,3(a0)
L(lb3):
sb a1,2(a0)
L(lb2):
sb a1,1(a0)
L(lb1):
sb a1,0(a0)
.Lset0:
andi v1,v1,0x3 # word-unaligned address?
beq v1,zero,.Laligned # v1 is the unalignment count
subu a2,a2,v1
SWHI a1,0(a0)
addu a0,a0,v1
li t9,NSIZE
subu t2,t9,t2
PTR_SUBU a2,a2,t2
PTR_ADDU a0,a0,t2
#endif /* R6_CODE */
# Here we have the "word-aligned" a0 (until the "last4")
.Laligned:
andi t8,a2,0x3f # any 64-byte chunks?
# t8 is the byte count past 64-byte chunks
beq a2,t8,.Lchk8w # when a2==t8, no 64-byte chunks
# There will be at most 1 32-byte chunk then
subu a3,a2,t8 # subtract from a2 the reminder
# Here a3 counts bytes in 16w chunks
addu a3,a0,a3 # Now a3 is the final dst after 64-byte chunks
# Find out, if there are any 64-byte chunks after which will be still at least
# 96 bytes left. The value "96" is calculated as needed buffer for
# "pref 30,64(a0)" prefetch, which can be used as "pref 30,0(a0)" after
# incrementing "a0" by 64.
# For "a2" below 160 there will be no such "pref 30 safe" 64-byte chunk.
#
sltiu v1,a2,160
bgtz v1,.Lloop16w_nopref30 # skip "pref 30,0(a0)"
subu t7,a2,96 # subtract "pref 30 unsafe" region
# below we have at least 1 64-byte chunk which is "pref 30 safe"
andi t6,t7,0x3f # t6 is past "64-byte safe chunks" reminder
subu t5,t7,t6 # subtract from t7 the reminder
# Here t5 counts bytes in 16w "safe" chunks
addu t4,a0,t5 # Now t4 is the dst after 64-byte "safe" chunks
# Don't use "pref 30,0(a0)" for a0 in a "middle" of a cache line
# pref 30,0(a0)
# Here we are in the region, where it is safe to use "pref 30,64(a0)"
.Lloop16w:
addiu a0,a0,64
pref 30,-32(a0) # continue setting up the dest, addr 64-32
sw a1,-64(a0)
sw a1,-60(a0)
sw a1,-56(a0)
sw a1,-52(a0)
sw a1,-48(a0)
sw a1,-44(a0)
sw a1,-40(a0)
sw a1,-36(a0)
nop
nop # the extra nop instructions help to balance
nop # cycles needed for "store" + "fill" + "evict"
nop # For 64byte store there are needed 8 fill
nop # and 8 evict cycles, i.e. at least 32 instr.
nop
nop
pref 30,0(a0) # continue setting up the dest, addr 64-0
sw a1,-32(a0)
sw a1,-28(a0)
sw a1,-24(a0)
sw a1,-20(a0)
sw a1,-16(a0)
sw a1,-12(a0)
sw a1,-8(a0)
sw a1,-4(a0)
nop
nop
nop
nop # NOTE: adding 14 nop-s instead of 12 nop-s
nop # gives better results for "fast" memory
nop
bne a0,t4,.Lloop16w
nop
beq a0,a3,.Lchk8w # maybe no more 64-byte chunks?
nop # this "delayed slot" is useless ...
.Lloop16w_nopref30: # there could be up to 3 "64-byte nopref30" chunks
addiu a0,a0,64
sw a1,-64(a0)
sw a1,-60(a0)
sw a1,-56(a0)
sw a1,-52(a0)
sw a1,-48(a0)
sw a1,-44(a0)
sw a1,-40(a0)
sw a1,-36(a0)
sw a1,-32(a0)
sw a1,-28(a0)
sw a1,-24(a0)
sw a1,-20(a0)
sw a1,-16(a0)
sw a1,-12(a0)
sw a1,-8(a0)
bne a0,a3,.Lloop16w_nopref30
sw a1,-4(a0)
.Lchk8w: # t8 here is the byte count past 64-byte chunks
andi t7,t8,0x1f # is there a 32-byte chunk?
# the t7 is the reminder count past 32-bytes
beq t8,t7,.Lchk1w # when t8==t7, no 32-byte chunk
move a2,t7
L(aligned):
/* If USE_DOUBLE is not set we may still want to align the data on a 16
byte boundry instead of an 8 byte boundry to maximize the opportunity
of proAptiv chips to do memory bonding (combining two sequential 4
byte stores into one 8 byte store). We know there are at least 4 bytes
left to store or we would have jumped to L(lastb) earlier in the code. */
#ifdef DOUBLE_ALIGN
andi t2,a3,4
beq t2,zero,L(double_aligned)
PTR_SUBU a2,a2,t2
sw a1,0(a0)
PTR_ADDU a0,a0,t2
L(double_aligned):
#endif
sw a1,4(a0)
sw a1,8(a0)
sw a1,12(a0)
sw a1,16(a0)
sw a1,20(a0)
sw a1,24(a0)
sw a1,28(a0)
addiu a0,a0,32
/* Now the destination is aligned to (word or double word) aligned address
Set a2 to count how many bytes we have to copy after all the 64/128 byte
chunks are copied and a3 to the dest pointer after all the 64/128 byte
chunks have been copied. We will loop, incrementing a0 until it equals
a3. */
andi t8,a2,NSIZEDMASK /* any whole 64-byte/128-byte chunks? */
beq a2,t8,L(chkw) /* if a2==t8, no 64-byte/128-byte chunks */
PTR_SUBU a3,a2,t8 /* subtract from a2 the reminder */
PTR_ADDU a3,a0,a3 /* Now a3 is the final dst after loop */
.Lchk1w:
andi t8,a2,0x3 # now t8 is the reminder past 1w chunks
beq a2,t8,.Llast4aligned
subu a3,a2,t8 # a3 is the count of bytes in 1w chunks
addu a3,a0,a3 # now a3 is the dst address past the 1w chunks
/* When in the loop we may prefetch with the 'prepare to store' hint,
in this case the a0+x should not be past the "t0-32" address. This
means: for x=128 the last "safe" a0 address is "t0-160". Alternatively,
for x=64 the last "safe" a0 address is "t0-96" In the current version we
will use "prefetch hint,128(a0)", so "t0-160" is the limit. */
#if defined(USE_PREFETCH) \
&& (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
PTR_ADDU t0,a0,a2 /* t0 is the "past the end" address */
PTR_SUBU t9,t0,PREFETCH_LIMIT /* t9 is the "last safe pref" address */
#endif
#if defined(USE_PREFETCH) \
&& (PREFETCH_STORE_HINT != PREFETCH_HINT_PREPAREFORSTORE)
PREFETCH_FOR_STORE (1, a0)
PREFETCH_FOR_STORE (2, a0)
PREFETCH_FOR_STORE (3, a0)
#endif
# copying in words (4-byte chunks)
.LwordCopy_loop:
addiu a0,a0,4
bne a0,a3,.LwordCopy_loop
sw a1,-4(a0)
L(loop16w):
#if defined(USE_PREFETCH) \
&& (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
sltu v1,t9,a0 /* If a0 > t9 don't use next prefetch */
bgtz v1,L(skip_pref)
nop
#endif
#ifndef R6_CODE
PREFETCH_FOR_STORE (4, a0)
PREFETCH_FOR_STORE (5, a0)
#else
PREFETCH_FOR_STORE (2, a0)
#endif
L(skip_pref):
C_ST a1,UNIT(0)(a0)
C_ST a1,UNIT(1)(a0)
C_ST a1,UNIT(2)(a0)
C_ST a1,UNIT(3)(a0)
C_ST a1,UNIT(4)(a0)
C_ST a1,UNIT(5)(a0)
C_ST a1,UNIT(6)(a0)
C_ST a1,UNIT(7)(a0)
C_ST a1,UNIT(8)(a0)
C_ST a1,UNIT(9)(a0)
C_ST a1,UNIT(10)(a0)
C_ST a1,UNIT(11)(a0)
C_ST a1,UNIT(12)(a0)
C_ST a1,UNIT(13)(a0)
C_ST a1,UNIT(14)(a0)
C_ST a1,UNIT(15)(a0)
PTR_ADDIU a0,a0,UNIT(16) /* adding 64/128 to dest */
bne a0,a3,L(loop16w)
nop
move a2,t8
/* Here we have dest word-aligned but less than 64-bytes or 128 bytes to go.
Check for a 32(64) byte chunk and copy if if there is one. Otherwise
jump down to L(chk1w) to handle the tail end of the copy. */
L(chkw):
andi t8,a2,NSIZEMASK /* is there a 32-byte/64-byte chunk. */
/* the t8 is the reminder count past 32-bytes */
beq a2,t8,L(chk1w)/* when a2==t8, no 32-byte chunk */
nop
C_ST a1,UNIT(0)(a0)
C_ST a1,UNIT(1)(a0)
C_ST a1,UNIT(2)(a0)
C_ST a1,UNIT(3)(a0)
C_ST a1,UNIT(4)(a0)
C_ST a1,UNIT(5)(a0)
C_ST a1,UNIT(6)(a0)
C_ST a1,UNIT(7)(a0)
PTR_ADDIU a0,a0,UNIT(8)
/* Here we have less than 32(64) bytes to set. Set up for a loop to
copy one word (or double word) at a time. Set a2 to count how many
bytes we have to copy after all the word (or double word) chunks are
copied and a3 to the dest pointer after all the (d)word chunks have
been copied. We will loop, incrementing a0 until a0 equals a3. */
L(chk1w):
andi a2,t8,(NSIZE-1) /* a2 is the reminder past one (d)word chunks */
beq a2,t8,L(lastb)
PTR_SUBU a3,t8,a2 /* a3 is count of bytes in one (d)word chunks */
PTR_ADDU a3,a0,a3 /* a3 is the dst address after loop */
/* copying in words (4-byte or 8 byte chunks) */
L(wordCopy_loop):
PTR_ADDIU a0,a0,UNIT(1)
bne a0,a3,L(wordCopy_loop)
C_ST a1,UNIT(-1)(a0)
/* Copy the last 8 (or 16) bytes */
L(lastb):
blez a2,L(leave)
PTR_ADDU a3,a0,a2 /* a3 is the last dst address */
L(lastbloop):
PTR_ADDIU a0,a0,1
bne a0,a3,L(lastbloop)
sb a1,-1(a0)
L(leave):
# store last 0-3 bytes
# this will repeat the last store if the memset finishes on a word boundary
.Llast4aligned:
j ra
nop
SWLO a1,-1(t0)
.Llast4:
beq a0,t0,.Llast4e
.Llast4l:
addiu a0,a0,1
bne a0,t0,.Llast4l
sb a1,-1(a0)
.Llast4e:
j ra
nop
.set at
.set reorder
END(MEMSET_NAME)
#ifndef __ANDROID__
# ifdef _LIBC
libc_hidden_builtin_def (MEMSET_NAME)
# endif
#endif
END(memset)
/************************************************************************
* Implementation : Static functions
************************************************************************/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014 The Android Open Source Project
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,26 +25,20 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <string.h>
#include <stdint.h>
#ifndef _SYS_PROCFS_H_
#define _SYS_PROCFS_H_
void* memset(void* dst, int c, size_t n)
{
char* q = dst;
char* end = q + n;
#include <sys/cdefs.h>
#include <sys/ucontext.h>
for (;;) {
if (q >= end) break; *q++ = (char) c;
if (q >= end) break; *q++ = (char) c;
if (q >= end) break; *q++ = (char) c;
if (q >= end) break; *q++ = (char) c;
}
__BEGIN_DECLS
typedef unsigned long elf_greg_t;
typedef elf_greg_t elf_gregset_t[NGREG];
typedef fpregset_t elf_fpregset_t;
typedef elf_gregset_t prgregset_t;
typedef elf_fpregset_t prfpregset_t;
typedef pid_t lwpid_t;
typedef void* psaddr_t;
__END_DECLS
#endif /* _SYS_PROCFS_H_ */
return dst;
}

View File

@@ -1,260 +0,0 @@
/*
* Copyright (c) 2014
* Imagination Technologies Limited.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY IMAGINATION TECHNOLOGIES LIMITED ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL IMAGINATION TECHNOLOGIES LIMITED BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifdef __ANDROID__
# include <private/bionic_asm.h>
#elif _LIBC
# include <sysdep.h>
# include <regdef.h>
# include <sys/asm.h>
#elif _COMPILING_NEWLIB
# include "machine/asm.h"
# include "machine/regdef.h"
#else
# include <regdef.h>
# include <sys/asm.h>
#endif
/* Technically strcmp should not read past the end of the strings being
compared. We will read a full word that may contain excess bits beyond
the NULL string terminator but unless ENABLE_READAHEAD is set, we will not
read the next word after the end of string. Setting ENABLE_READAHEAD will
improve performance but is technically illegal based on the definition of
strcmp. */
#ifdef ENABLE_READAHEAD
# define DELAY_READ
#else
# define DELAY_READ nop
#endif
/* Testing on a little endian machine showed using CLZ was a
performance loss, so we are not turning it on by default. */
#if defined(ENABLE_CLZ) && (__mips_isa_rev > 1)
# define USE_CLZ
#endif
/* Some asm.h files do not have the L macro definition. */
#ifndef L
# if _MIPS_SIM == _ABIO32
# define L(label) $L ## label
# else
# define L(label) .L ## label
# endif
#endif
/* Some asm.h files do not have the PTR_ADDIU macro definition. */
#ifndef PTR_ADDIU
# if _MIPS_SIM == _ABIO32
# define PTR_ADDIU addiu
# else
# define PTR_ADDIU daddiu
# endif
#endif
/* Allow the routine to be named something else if desired. */
#ifndef STRCMP_NAME
# define STRCMP_NAME strcmp
#endif
#ifdef __ANDROID__
LEAF(STRCMP_NAME, 0)
#else
LEAF(STRCMP_NAME)
#endif
.set nomips16
.set noreorder
or t0, a0, a1
andi t0,0x3
bne t0, zero, L(byteloop)
/* Both strings are 4 byte aligned at this point. */
lui t8, 0x0101
ori t8, t8, 0x0101
lui t9, 0x7f7f
ori t9, 0x7f7f
#define STRCMP32(OFFSET) \
lw v0, OFFSET(a0); \
lw v1, OFFSET(a1); \
subu t0, v0, t8; \
bne v0, v1, L(worddiff); \
nor t1, v0, t9; \
and t0, t0, t1; \
bne t0, zero, L(returnzero)
L(wordloop):
STRCMP32(0)
DELAY_READ
STRCMP32(4)
DELAY_READ
STRCMP32(8)
DELAY_READ
STRCMP32(12)
DELAY_READ
STRCMP32(16)
DELAY_READ
STRCMP32(20)
DELAY_READ
STRCMP32(24)
DELAY_READ
STRCMP32(28)
PTR_ADDIU a0, a0, 32
b L(wordloop)
PTR_ADDIU a1, a1, 32
L(returnzero):
j ra
move v0, zero
L(worddiff):
#ifdef USE_CLZ
subu t0, v0, t8
nor t1, v0, t9
and t1, t0, t1
xor t0, v0, v1
or t0, t0, t1
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
wsbh t0, t0
rotr t0, t0, 16
# endif
clz t1, t0
and t1, 0xf8
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
neg t1
addu t1, 24
# endif
rotrv v0, v0, t1
rotrv v1, v1, t1
and v0, v0, 0xff
and v1, v1, 0xff
j ra
subu v0, v0, v1
#else /* USE_CLZ */
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
andi t0, v0, 0xff
beq t0, zero, L(wexit01)
andi t1, v1, 0xff
bne t0, t1, L(wexit01)
srl t8, v0, 8
srl t9, v1, 8
andi t8, t8, 0xff
beq t8, zero, L(wexit89)
andi t9, t9, 0xff
bne t8, t9, L(wexit89)
srl t0, v0, 16
srl t1, v1, 16
andi t0, t0, 0xff
beq t0, zero, L(wexit01)
andi t1, t1, 0xff
bne t0, t1, L(wexit01)
srl t8, v0, 24
srl t9, v1, 24
# else /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
srl t0, v0, 24
beq t0, zero, L(wexit01)
srl t1, v1, 24
bne t0, t1, L(wexit01)
srl t8, v0, 16
srl t9, v1, 16
andi t8, t8, 0xff
beq t8, zero, L(wexit89)
andi t9, t9, 0xff
bne t8, t9, L(wexit89)
srl t0, v0, 8
srl t1, v1, 8
andi t0, t0, 0xff
beq t0, zero, L(wexit01)
andi t1, t1, 0xff
bne t0, t1, L(wexit01)
andi t8, v0, 0xff
andi t9, v1, 0xff
# endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
L(wexit89):
j ra
subu v0, t8, t9
L(wexit01):
j ra
subu v0, t0, t1
#endif /* USE_CLZ */
/* It might seem better to do the 'beq' instruction between the two 'lbu'
instructions so that the nop is not needed but testing showed that this
code is actually faster (based on glibc strcmp test). */
#define BYTECMP01(OFFSET) \
lbu v0, OFFSET(a0); \
lbu v1, OFFSET(a1); \
beq v0, zero, L(bexit01); \
nop; \
bne v0, v1, L(bexit01)
#define BYTECMP89(OFFSET) \
lbu t8, OFFSET(a0); \
lbu t9, OFFSET(a1); \
beq t8, zero, L(bexit89); \
nop; \
bne t8, t9, L(bexit89)
L(byteloop):
BYTECMP01(0)
BYTECMP89(1)
BYTECMP01(2)
BYTECMP89(3)
BYTECMP01(4)
BYTECMP89(5)
BYTECMP01(6)
BYTECMP89(7)
PTR_ADDIU a0, a0, 8
b L(byteloop)
PTR_ADDIU a1, a1, 8
L(bexit01):
j ra
subu v0, v0, v1
L(bexit89):
j ra
subu v0, t8, t9
.set at
.set reorder
END(STRCMP_NAME)
#ifndef __ANDROID__
# ifdef _LIBC
libc_hidden_builtin_def (STRCMP_NAME)
# endif
#endif

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___clock_nanosleep)
ENTRY(__clock_nanosleep)
.set noreorder
.cpload t9
li v0, __NR_clock_nanosleep
@@ -16,5 +16,4 @@ ENTRY(___clock_nanosleep)
j t9
nop
.set reorder
END(___clock_nanosleep)
.hidden ___clock_nanosleep
END(__clock_nanosleep)

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___fgetxattr)
ENTRY(fgetxattr)
.set noreorder
.cpload t9
li v0, __NR_fgetxattr
@@ -16,5 +16,4 @@ ENTRY(___fgetxattr)
j t9
nop
.set reorder
END(___fgetxattr)
.hidden ___fgetxattr
END(fgetxattr)

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___fsetxattr)
ENTRY(fsetxattr)
.set noreorder
.cpload t9
li v0, __NR_fsetxattr
@@ -16,5 +16,4 @@ ENTRY(___fsetxattr)
j t9
nop
.set reorder
END(___fsetxattr)
.hidden ___fsetxattr
END(fsetxattr)

View File

@@ -1,19 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(process_vm_readv)
.set noreorder
.cpload t9
li v0, __NR_process_vm_readv
syscall
bnez a3, 1f
move a0, v0
j ra
nop
1:
la t9,__set_errno_internal
j t9
nop
.set reorder
END(process_vm_readv)

View File

@@ -1,19 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(process_vm_writev)
.set noreorder
.cpload t9
li v0, __NR_process_vm_writev
syscall
bnez a3, 1f
move a0, v0
j ra
nop
1:
la t9,__set_errno_internal
j t9
nop
.set reorder
END(process_vm_writev)

View File

@@ -32,28 +32,29 @@
#include <unistd.h>
struct kernel_stat {
unsigned int st_dev;
unsigned int st_pad0[3];
unsigned long st_ino;
mode_t st_mode;
__u32 st_nlink;
uid_t st_uid;
gid_t st_gid;
unsigned int st_rdev;
unsigned int st_pad1[3];
__kernel_off_t st_size;
unsigned int _st_atime;
unsigned int st_atime_nsec;
unsigned int _st_mtime;
unsigned int st_mtime_nsec;
unsigned int _st_ctime;
unsigned int st_ctime_nsec;
unsigned int st_blksize;
unsigned int st_pad2;
unsigned long st_blocks;
unsigned int st_dev;
unsigned int st_pad0[3];
unsigned long st_ino;
mode_t st_mode;
__u32 st_nlink;
uid_t st_uid;
gid_t st_gid;
unsigned int st_rdev;
unsigned int st_pad1[3];
__kernel_off_t st_size;
unsigned int _st_atime;
unsigned int st_atime_nsec;
unsigned int _st_mtime;
unsigned int st_mtime_nsec;
unsigned int _st_ctime;
unsigned int st_ctime_nsec;
unsigned int st_blksize;
unsigned int st_pad2;
unsigned long st_blocks;
};
static void copy_stat(struct stat* st, struct kernel_stat* s) {
void copy_stat(struct stat *st, struct kernel_stat *s)
{
st->st_dev = static_cast<dev_t>(s->st_dev);
st->st_ino = static_cast<ino_t>(s->st_ino);
st->st_mode = static_cast<mode_t>(s->st_mode);
@@ -72,17 +73,30 @@ static void copy_stat(struct stat* st, struct kernel_stat* s) {
st->st_ctim.tv_nsec = static_cast<long>(s->st_ctime_nsec);
}
int fstat(int fp, struct stat* st) {
int fstat(int fp, struct stat *st)
{
kernel_stat s;
int ret = syscall(__NR_fstat, fp, &s);
copy_stat(st, &s);
int ret;
ret = syscall (__NR_fstat, fp, &s);
copy_stat (st, &s);
return ret;
}
__strong_alias(fstat64, fstat);
int fstatat(int dirfd, const char* pathname, struct stat* buf, int flags) {
int newfstatat(int dirfd, const char *pathname, struct stat *buf, int flags)
{
kernel_stat s;
int ret = syscall(__NR_newfstatat, dirfd, pathname, &s, flags);
int ret;
ret = syscall(__NR_newfstatat, dirfd, pathname, &s, flags);
copy_stat(buf, &s);
return ret;
}
int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags)
{
kernel_stat s;
int ret;
ret = syscall(__NR_newfstatat, dirfd, pathname, &s, flags);
copy_stat(buf, &s);
return ret;
}

View File

@@ -5,11 +5,6 @@
#
libc_bionic_src_files_mips64 += \
arch-mips/string/memcmp.c \
arch-mips/string/memcpy.S \
arch-mips/string/memset.S \
arch-mips/string/strcmp.S \
arch-mips/string/strlen.c \
bionic/__memcpy_chk.cpp \
bionic/__memset_chk.cpp \
bionic/__strcpy_chk.cpp \
@@ -17,6 +12,10 @@ libc_bionic_src_files_mips64 += \
bionic/strchr.cpp \
bionic/strnlen.c \
bionic/strrchr.cpp \
arch-mips/string/memcmp.c \
arch-mips/string/memcpy.c \
arch-mips/string/memset.c \
arch-mips/string/strlen.c \
libc_freebsd_src_files_mips64 += \
upstream-freebsd/lib/libc/string/wcscat.c \
@@ -35,6 +34,7 @@ libc_openbsd_src_files_mips64 += \
upstream-openbsd/lib/libc/string/stpcpy.c \
upstream-openbsd/lib/libc/string/stpncpy.c \
upstream-openbsd/lib/libc/string/strcat.c \
upstream-openbsd/lib/libc/string/strcmp.c \
upstream-openbsd/lib/libc/string/strcpy.c \
upstream-openbsd/lib/libc/string/strlcat.c \
upstream-openbsd/lib/libc/string/strlcpy.c \

View File

@@ -0,0 +1,423 @@
/*
* Copyright (c) 2009
* MIPS Technologies, Inc., California.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/************************************************************************
*
* memcpy.S
* Version: "043009"
*
************************************************************************/
/************************************************************************
* Include files
************************************************************************/
#include <private/bionic_asm.h>
/*
* This routine could be optimized for MIPS64. The current code only
* uses MIPS32 instructions.
*/
#if defined(__MIPSEB__)
# define LWHI lwl /* high part is left in big-endian */
# define SWHI swl /* high part is left in big-endian */
# define LWLO lwr /* low part is right in big-endian */
# define SWLO swr /* low part is right in big-endian */
#endif
#if defined(__MIPSEL__)
# define LWHI lwr /* high part is right in little-endian */
# define SWHI swr /* high part is right in little-endian */
# define LWLO lwl /* low part is left in big-endian */
# define SWLO swl /* low part is left in big-endian */
#endif
LEAF(memcpy,0)
.set noreorder
.set noat
/*
* Below we handle the case where memcpy is called with overlapping src and dst.
* Although memcpy is not required to handle this case, some parts of Android like Skia
* rely on such usage. We call memmove to handle such cases.
*/
subu t0,a0,a1
sra AT,t0,31
xor t1,t0,AT
subu t0,t1,AT
sltu AT,t0,a2
beq AT,zero,.Lmemcpy
la t9,memmove
jr t9
nop
.Lmemcpy:
slti AT,a2,8
bne AT,zero,.Llast8
move v0,a0 # memcpy returns the dst pointer
# Test if the src and dst are word-aligned, or can be made word-aligned
xor t8,a1,a0
andi t8,t8,0x3 # t8 is a0/a1 word-displacement
bne t8,zero,.Lunaligned
negu a3,a0
andi a3,a3,0x3 # we need to copy a3 bytes to make a0/a1 aligned
beq a3,zero,.Lchk16w # when a3=0 then the dst (a0) is word-aligned
subu a2,a2,a3 # now a2 is the remining bytes count
LWHI t8,0(a1)
addu a1,a1,a3
SWHI t8,0(a0)
addu a0,a0,a3
# Now the dst/src are mutually word-aligned with word-aligned addresses
.Lchk16w:
andi t8,a2,0x3f # any whole 64-byte chunks?
# t8 is the byte count after 64-byte chunks
beq a2,t8,.Lchk8w # if a2==t8, no 64-byte chunks
# There will be at most 1 32-byte chunk after it
subu a3,a2,t8 # subtract from a2 the reminder
# Here a3 counts bytes in 16w chunks
addu a3,a0,a3 # Now a3 is the final dst after 64-byte chunks
addu t0,a0,a2 # t0 is the "past the end" address
# When in the loop we exercise "pref 30,x(a0)", the a0+x should not be past
# the "t0-32" address
# This means: for x=128 the last "safe" a0 address is "t0-160"
# Alternatively, for x=64 the last "safe" a0 address is "t0-96"
# In the current version we will use "pref 30,128(a0)", so "t0-160" is the limit
subu t9,t0,160 # t9 is the "last safe pref 30,128(a0)" address
pref 0,0(a1) # bring the first line of src, addr 0
pref 0,32(a1) # bring the second line of src, addr 32
pref 0,64(a1) # bring the third line of src, addr 64
pref 30,32(a0) # safe, as we have at least 64 bytes ahead
# In case the a0 > t9 don't use "pref 30" at all
sgtu v1,a0,t9
bgtz v1,.Lloop16w # skip "pref 30,64(a0)" for too short arrays
nop
# otherwise, start with using pref30
pref 30,64(a0)
.Lloop16w:
pref 0,96(a1)
lw t0,0(a1)
bgtz v1,.Lskip_pref30_96 # skip "pref 30,96(a0)"
lw t1,4(a1)
pref 30,96(a0) # continue setting up the dest, addr 96
.Lskip_pref30_96:
lw t2,8(a1)
lw t3,12(a1)
lw t4,16(a1)
lw t5,20(a1)
lw t6,24(a1)
lw t7,28(a1)
pref 0,128(a1) # bring the next lines of src, addr 128
sw t0,0(a0)
sw t1,4(a0)
sw t2,8(a0)
sw t3,12(a0)
sw t4,16(a0)
sw t5,20(a0)
sw t6,24(a0)
sw t7,28(a0)
lw t0,32(a1)
bgtz v1,.Lskip_pref30_128 # skip "pref 30,128(a0)"
lw t1,36(a1)
pref 30,128(a0) # continue setting up the dest, addr 128
.Lskip_pref30_128:
lw t2,40(a1)
lw t3,44(a1)
lw t4,48(a1)
lw t5,52(a1)
lw t6,56(a1)
lw t7,60(a1)
pref 0, 160(a1) # bring the next lines of src, addr 160
sw t0,32(a0)
sw t1,36(a0)
sw t2,40(a0)
sw t3,44(a0)
sw t4,48(a0)
sw t5,52(a0)
sw t6,56(a0)
sw t7,60(a0)
addiu a0,a0,64 # adding 64 to dest
sgtu v1,a0,t9
bne a0,a3,.Lloop16w
addiu a1,a1,64 # adding 64 to src
move a2,t8
# Here we have src and dest word-aligned but less than 64-bytes to go
.Lchk8w:
pref 0, 0x0(a1)
andi t8,a2,0x1f # is there a 32-byte chunk?
# the t8 is the reminder count past 32-bytes
beq a2,t8,.Lchk1w # when a2=t8, no 32-byte chunk
nop
lw t0,0(a1)
lw t1,4(a1)
lw t2,8(a1)
lw t3,12(a1)
lw t4,16(a1)
lw t5,20(a1)
lw t6,24(a1)
lw t7,28(a1)
addiu a1,a1,32
sw t0,0(a0)
sw t1,4(a0)
sw t2,8(a0)
sw t3,12(a0)
sw t4,16(a0)
sw t5,20(a0)
sw t6,24(a0)
sw t7,28(a0)
addiu a0,a0,32
.Lchk1w:
andi a2,t8,0x3 # now a2 is the reminder past 1w chunks
beq a2,t8,.Llast8
subu a3,t8,a2 # a3 is count of bytes in 1w chunks
addu a3,a0,a3 # now a3 is the dst address past the 1w chunks
# copying in words (4-byte chunks)
.LwordCopy_loop:
lw t3,0(a1) # the first t3 may be equal t0 ... optimize?
addiu a1,a1,4
addiu a0,a0,4
bne a0,a3,.LwordCopy_loop
sw t3,-4(a0)
# For the last (<8) bytes
.Llast8:
blez a2,.Lleave
addu a3,a0,a2 # a3 is the last dst address
.Llast8loop:
lb v1,0(a1)
addiu a1,a1,1
addiu a0,a0,1
bne a0,a3,.Llast8loop
sb v1,-1(a0)
.Lleave:
j ra
nop
#
# UNALIGNED case
#
.Lunaligned:
# got here with a3="negu a0"
andi a3,a3,0x3 # test if the a0 is word aligned
beqz a3,.Lua_chk16w
subu a2,a2,a3 # bytes left after initial a3 bytes
LWHI v1,0(a1)
LWLO v1,3(a1)
addu a1,a1,a3 # a3 may be here 1, 2 or 3
SWHI v1,0(a0)
addu a0,a0,a3 # below the dst will be word aligned (NOTE1)
.Lua_chk16w:
andi t8,a2,0x3f # any whole 64-byte chunks?
# t8 is the byte count after 64-byte chunks
beq a2,t8,.Lua_chk8w # if a2==t8, no 64-byte chunks
# There will be at most 1 32-byte chunk after it
subu a3,a2,t8 # subtract from a2 the reminder
# Here a3 counts bytes in 16w chunks
addu a3,a0,a3 # Now a3 is the final dst after 64-byte chunks
addu t0,a0,a2 # t0 is the "past the end" address
subu t9,t0,160 # t9 is the "last safe pref 30,128(a0)" address
pref 0,0(a1) # bring the first line of src, addr 0
pref 0,32(a1) # bring the second line of src, addr 32
pref 0,64(a1) # bring the third line of src, addr 64
pref 30,32(a0) # safe, as we have at least 64 bytes ahead
# In case the a0 > t9 don't use "pref 30" at all
sgtu v1,a0,t9
bgtz v1,.Lua_loop16w # skip "pref 30,64(a0)" for too short arrays
nop
# otherwise, start with using pref30
pref 30,64(a0)
.Lua_loop16w:
pref 0,96(a1)
LWHI t0,0(a1)
LWLO t0,3(a1)
LWHI t1,4(a1)
bgtz v1,.Lua_skip_pref30_96
LWLO t1,7(a1)
pref 30,96(a0) # continue setting up the dest, addr 96
.Lua_skip_pref30_96:
LWHI t2,8(a1)
LWLO t2,11(a1)
LWHI t3,12(a1)
LWLO t3,15(a1)
LWHI t4,16(a1)
LWLO t4,19(a1)
LWHI t5,20(a1)
LWLO t5,23(a1)
LWHI t6,24(a1)
LWLO t6,27(a1)
LWHI t7,28(a1)
LWLO t7,31(a1)
pref 0,128(a1) # bring the next lines of src, addr 128
sw t0,0(a0)
sw t1,4(a0)
sw t2,8(a0)
sw t3,12(a0)
sw t4,16(a0)
sw t5,20(a0)
sw t6,24(a0)
sw t7,28(a0)
LWHI t0,32(a1)
LWLO t0,35(a1)
LWHI t1,36(a1)
bgtz v1,.Lua_skip_pref30_128
LWLO t1,39(a1)
pref 30,128(a0) # continue setting up the dest, addr 128
.Lua_skip_pref30_128:
LWHI t2,40(a1)
LWLO t2,43(a1)
LWHI t3,44(a1)
LWLO t3,47(a1)
LWHI t4,48(a1)
LWLO t4,51(a1)
LWHI t5,52(a1)
LWLO t5,55(a1)
LWHI t6,56(a1)
LWLO t6,59(a1)
LWHI t7,60(a1)
LWLO t7,63(a1)
pref 0, 160(a1) # bring the next lines of src, addr 160
sw t0,32(a0)
sw t1,36(a0)
sw t2,40(a0)
sw t3,44(a0)
sw t4,48(a0)
sw t5,52(a0)
sw t6,56(a0)
sw t7,60(a0)
addiu a0,a0,64 # adding 64 to dest
sgtu v1,a0,t9
bne a0,a3,.Lua_loop16w
addiu a1,a1,64 # adding 64 to src
move a2,t8
# Here we have src and dest word-aligned but less than 64-bytes to go
.Lua_chk8w:
pref 0, 0x0(a1)
andi t8,a2,0x1f # is there a 32-byte chunk?
# the t8 is the reminder count
beq a2,t8,.Lua_chk1w # when a2=t8, no 32-byte chunk
nop
LWHI t0,0(a1)
LWLO t0,3(a1)
LWHI t1,4(a1)
LWLO t1,7(a1)
LWHI t2,8(a1)
LWLO t2,11(a1)
LWHI t3,12(a1)
LWLO t3,15(a1)
LWHI t4,16(a1)
LWLO t4,19(a1)
LWHI t5,20(a1)
LWLO t5,23(a1)
LWHI t6,24(a1)
LWLO t6,27(a1)
LWHI t7,28(a1)
LWLO t7,31(a1)
addiu a1,a1,32
sw t0,0(a0)
sw t1,4(a0)
sw t2,8(a0)
sw t3,12(a0)
sw t4,16(a0)
sw t5,20(a0)
sw t6,24(a0)
sw t7,28(a0)
addiu a0,a0,32
.Lua_chk1w:
andi a2,t8,0x3 # now a2 is the reminder past 1w chunks
beq a2,t8,.Lua_smallCopy
subu a3,t8,a2 # a3 is count of bytes in 1w chunks
addu a3,a0,a3 # now a3 is the dst address past the 1w chunks
# copying in words (4-byte chunks)
.Lua_wordCopy_loop:
LWHI v1,0(a1)
LWLO v1,3(a1)
addiu a1,a1,4
addiu a0,a0,4 # note: dst=a0 is word aligned here, see NOTE1
bne a0,a3,.Lua_wordCopy_loop
sw v1,-4(a0)
# Now less than 4 bytes (value in a2) left to copy
.Lua_smallCopy:
beqz a2,.Lleave
addu a3,a0,a2 # a3 is the last dst address
.Lua_smallCopy_loop:
lb v1,0(a1)
addiu a1,a1,1
addiu a0,a0,1
bne a0,a3,.Lua_smallCopy_loop
sb v1,-1(a0)
j ra
nop
.set at
.set reorder
END(memcpy)
/************************************************************************
* Implementation : Static functions
************************************************************************/

View File

@@ -0,0 +1,242 @@
/*
* Copyright (c) 2009
* MIPS Technologies, Inc., California.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/************************************************************************
*
* memset.S, version "64h" with 1 cache line horizon for "pref 30" and 14 nops
* Version: "043009"
*
************************************************************************/
/************************************************************************
* Include files
************************************************************************/
#include <private/bionic_asm.h>
/*
* This routine could be optimized for MIPS64. The current code only
* uses MIPS32 instructions.
*/
#if defined(__MIPSEB__)
# define SWHI swl /* high part is left in big-endian */
# define SWLO swr /* low part is right in big-endian */
#endif
#if defined(__MIPSEL__)
# define SWHI swr /* high part is right in little-endian */
# define SWLO swl /* low part is left in little-endian */
#endif
#if !(defined(XGPROF) || defined(XPROF))
#undef SETUP_GP
#define SETUP_GP
#endif
#ifdef NDEBUG
#define DBG #
#else
#define DBG
#endif
LEAF(memset,0)
.set noreorder
.set noat
addu t0,a0,a2 # t0 is the "past the end" address
slti AT,a2,4 # is a2 less than 4?
bne AT,zero,.Llast4 # if yes, go to last4
move v0,a0 # memset returns the dst pointer
beq a1,zero,.Lset0
subu v1,zero,a0
# smear byte into 32 bit word
#if (__mips==32) && (__mips_isa_rev>=2)
ins a1, a1, 8, 8 # Replicate fill byte into half-word.
ins a1, a1, 16, 16 # Replicate fill byte into word.
#else
and a1,0xff
sll AT,a1,8
or a1,AT
sll AT,a1,16
or a1,AT
#endif
.Lset0:
andi v1,v1,0x3 # word-unaligned address?
beq v1,zero,.Laligned # v1 is the unalignment count
subu a2,a2,v1
SWHI a1,0(a0)
addu a0,a0,v1
# Here we have the "word-aligned" a0 (until the "last4")
.Laligned:
andi t8,a2,0x3f # any 64-byte chunks?
# t8 is the byte count past 64-byte chunks
beq a2,t8,.Lchk8w # when a2==t8, no 64-byte chunks
# There will be at most 1 32-byte chunk then
subu a3,a2,t8 # subtract from a2 the reminder
# Here a3 counts bytes in 16w chunks
addu a3,a0,a3 # Now a3 is the final dst after 64-byte chunks
# Find out, if there are any 64-byte chunks after which will be still at least
# 96 bytes left. The value "96" is calculated as needed buffer for
# "pref 30,64(a0)" prefetch, which can be used as "pref 30,0(a0)" after
# incrementing "a0" by 64.
# For "a2" below 160 there will be no such "pref 30 safe" 64-byte chunk.
#
sltiu v1,a2,160
bgtz v1,.Lloop16w_nopref30 # skip "pref 30,0(a0)"
subu t7,a2,96 # subtract "pref 30 unsafe" region
# below we have at least 1 64-byte chunk which is "pref 30 safe"
andi t6,t7,0x3f # t6 is past "64-byte safe chunks" reminder
subu t5,t7,t6 # subtract from t7 the reminder
# Here t5 counts bytes in 16w "safe" chunks
addu t4,a0,t5 # Now t4 is the dst after 64-byte "safe" chunks
# Don't use "pref 30,0(a0)" for a0 in a "middle" of a cache line
# pref 30,0(a0)
# Here we are in the region, where it is safe to use "pref 30,64(a0)"
.Lloop16w:
addiu a0,a0,64
pref 30,-32(a0) # continue setting up the dest, addr 64-32
sw a1,-64(a0)
sw a1,-60(a0)
sw a1,-56(a0)
sw a1,-52(a0)
sw a1,-48(a0)
sw a1,-44(a0)
sw a1,-40(a0)
sw a1,-36(a0)
nop
nop # the extra nop instructions help to balance
nop # cycles needed for "store" + "fill" + "evict"
nop # For 64byte store there are needed 8 fill
nop # and 8 evict cycles, i.e. at least 32 instr.
nop
nop
pref 30,0(a0) # continue setting up the dest, addr 64-0
sw a1,-32(a0)
sw a1,-28(a0)
sw a1,-24(a0)
sw a1,-20(a0)
sw a1,-16(a0)
sw a1,-12(a0)
sw a1,-8(a0)
sw a1,-4(a0)
nop
nop
nop
nop # NOTE: adding 14 nop-s instead of 12 nop-s
nop # gives better results for "fast" memory
nop
bne a0,t4,.Lloop16w
nop
beq a0,a3,.Lchk8w # maybe no more 64-byte chunks?
nop # this "delayed slot" is useless ...
.Lloop16w_nopref30: # there could be up to 3 "64-byte nopref30" chunks
addiu a0,a0,64
sw a1,-64(a0)
sw a1,-60(a0)
sw a1,-56(a0)
sw a1,-52(a0)
sw a1,-48(a0)
sw a1,-44(a0)
sw a1,-40(a0)
sw a1,-36(a0)
sw a1,-32(a0)
sw a1,-28(a0)
sw a1,-24(a0)
sw a1,-20(a0)
sw a1,-16(a0)
sw a1,-12(a0)
sw a1,-8(a0)
bne a0,a3,.Lloop16w_nopref30
sw a1,-4(a0)
.Lchk8w: # t8 here is the byte count past 64-byte chunks
andi t7,t8,0x1f # is there a 32-byte chunk?
# the t7 is the reminder count past 32-bytes
beq t8,t7,.Lchk1w # when t8==t7, no 32-byte chunk
move a2,t7
sw a1,0(a0)
sw a1,4(a0)
sw a1,8(a0)
sw a1,12(a0)
sw a1,16(a0)
sw a1,20(a0)
sw a1,24(a0)
sw a1,28(a0)
addiu a0,a0,32
.Lchk1w:
andi t8,a2,0x3 # now t8 is the reminder past 1w chunks
beq a2,t8,.Llast4aligned
subu a3,a2,t8 # a3 is the count of bytes in 1w chunks
addu a3,a0,a3 # now a3 is the dst address past the 1w chunks
# copying in words (4-byte chunks)
.LwordCopy_loop:
addiu a0,a0,4
bne a0,a3,.LwordCopy_loop
sw a1,-4(a0)
# store last 0-3 bytes
# this will repeat the last store if the memset finishes on a word boundary
.Llast4aligned:
j ra
SWLO a1,-1(t0)
.Llast4:
beq a0,t0,.Llast4e
.Llast4l:
addiu a0,a0,1
bne a0,t0,.Llast4l
sb a1,-1(a0)
.Llast4e:
j ra
nop
.set at
.set reorder
END(memset)
/************************************************************************
* Implementation : Static functions
************************************************************************/

View File

@@ -0,0 +1,148 @@
/*
* Copyright (c) 2010 MIPS Technologies, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with
* the distribution.
* * Neither the name of MIPS Technologies Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __MIPS_STRING_OPS_H
#define __MIPS_STRING_OPS_H
/* This definition of the byte bitfields uses the
assumption that the layout of the bitfields is
equivalent to the layout in memory. Generally,
for the MIPS ABIs, this is true. If you compile
the strcmp.c file with -DSMOKE_TEST_NEW_STRCMP,
this assumption will be tested.
Also, regardless of char signedness, ANSI C dictates that
strcmp() treats each character as unsigned char. For
strlen and the like, signedness doesn't matter.
Also, this code assumes that there are 8-bits per 'char'. */
#if __mips64
typedef struct bits
{
unsigned long B0:8, B1:8, B2:8, B3:8, B4:8, B5:8, B6:8, B7:8;
} bits_t;
#else
typedef struct bits
{
unsigned long B0:8, B1:8, B2:8, B3:8;
} bits_t;
#endif
#ifndef _ULW
/* for MIPS GCC, there is no unaligned builtins - so this code forces
the compiler to treat the pointer access as unaligned. */
struct ulw
{
unsigned long b;
} __attribute__ ((packed));
#define _ULW(__x) ((struct ulw *) ((char *)(&__x)))->b;
#endif
/* This union assumes that small structures can be in registers. If
not, then memory accesses will be done - not optimal, but ok. */
typedef union
{
unsigned long v;
bits_t b;
} bitfields_t;
#ifndef detect_zero
/* __mips_dsp, __mips_dspr2, and __mips64 are predefined by
the compiler, based on command line options. */
#if (__mips_dsp || __mips_dspr2) && !__mips64
#define __mips_using_dsp 1
/* DSP 4-lane (8 unsigned bits per line) subtract and saturate
* Intrinsic operation. How this works:
* Given a 4-byte string of "ABC\0", subtract this as
* an unsigned integer from 0x01010101:
* 0x01010101
* - 0x41424300
* -----------
( 0xbfbebe01 <-- answer without saturation
* 0x00000001 <-- answer with saturation
* When this 4-lane vector is treated as an unsigned int value,
* a non-zero answer indicates the presence of a zero in the
* original 4-byte argument. */
typedef signed char v4i8 __attribute__ ((vector_size (4)));
#define detect_zero(__x,__y,__01s,__80s)\
((unsigned) __builtin_mips_subu_s_qb((v4i8) __01s,(v4i8) __x))
/* sets all 4 lanes to requested byte. */
#define set_byte_lanes(__x) ((unsigned) __builtin_mips_repl_qb(__x))
/* sets all 4 lanes to 0x01. */
#define def_and_set_01(__x) unsigned long __x = (unsigned) __builtin_mips_repl_qb(0x01)
/* sets all 4 lanes to 0x80. Not needed when subu_s.qb used. */
#define def_and_set_80(__x) /* do nothing */
#else
/* this version, originally published in the 80's, uses
a reverse-carry-set like determination of the zero byte.
The steps are, for __x = 0x31ff0001:
__x - _01s = 0x30fdff00
~__x = 0xce00fffe
((__x - _01s) & ~__x) = 0x0000ff00
x & _80s = 0x00008000 <- byte 3 was zero
Some implementaions naively assume that characters are
always 7-bit unsigned ASCII. With that assumption, the
"& ~x" is usually discarded. Since character strings
are 8-bit, the and is needed to catch the case of
a false positive when the byte is 0x80. */
#define detect_zero(__x,__y,_01s,_80s)\
((unsigned) (((__x) - _01s) & ~(__x)) & _80s)
#if __mips64
#define def_and_set_80(__x) unsigned long __x = 0x8080808080808080ul
#define def_and_set_01(__x) unsigned long __x = 0x0101010101010101ul
#else
#define def_and_set_80(__x) unsigned long __x = 0x80808080ul
#define def_and_set_01(__x) unsigned long __x = 0x01010101ul
#endif
#endif
#endif
/* dealing with 'void *' conversions without using extra variables. */
#define get_byte(__x,__idx) (((unsigned char *) (__x))[__idx])
#define set_byte(__x,__idx,__fill) ((unsigned char *) (__x))[__idx] = (__fill)
#define get_word(__x,__idx) (((unsigned long *) (__x))[__idx])
#define set_word(__x,__idx,__fill) ((unsigned long *) (__x))[__idx] = (__fill)
#define inc_ptr_as(__type,__x,__inc) __x = (void *) (((__type) __x) + (__inc))
#define cvt_ptr_to(__type,__x) ((__type) (__x))
#endif

View File

@@ -0,0 +1,224 @@
/*
* Copyright (c) 2010 MIPS Technologies, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with
* the distribution.
* * Neither the name of MIPS Technologies Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include "mips-string-ops.h"
#define do_strlen_word(__av) {\
if (detect_zero(x,x,_01s,_80s)) break;\
x = __av;\
cnt += sizeof (unsigned);\
}
#define do_strlen_byte(__x) {\
if ((bx.b.B##__x) == 0) break;\
++cnt;\
}
#if SMOKE_TEST_MIPS_STRLEN
#define strlen my_strlen
#endif
size_t
strlen (const char *_a)
{
int cnt = 0;
unsigned long x;
/* align the string to word boundary so we can do word at a time. */
if ((cvt_ptr_to (unsigned long, _a) & (sizeof (unsigned long) - 1)) != 0)
{
if ((cvt_ptr_to (unsigned long, _a) & 1) != 0)
{
if (get_byte (_a, 0) == 0)
return cnt;
/* set bit 1 so 2-bytes are checked and incremented. */
inc_ptr_as (char *, _a, 1);
++cnt;
}
if ((cvt_ptr_to (unsigned long, _a) & 2) != 0)
{
if (get_byte (_a, 0) == 0)
return cnt + 0;
if (get_byte (_a, 1) == 0)
return cnt + 1;
inc_ptr_as (char *, _a, 2);
cnt += 2;
}
}
#if __mips64
#error strlen: mips64 check for 4-byte alignment not implemented.
#endif
if (1)
{
def_and_set_01 (_01s);
def_and_set_80 (_80s);
/* as advantagous as it is to performance, this code cannot pre-load
the following word, nor can it prefetch the next line at the start
of the loop since the string can be at the end of a page with the
following page unmapped. There are tests in the suite to catch
any attempt to go beyond the current word. */
x = get_word (_a, 0);
while (1)
{
/* doing 8 words should cover most strings. */
do_strlen_word (get_word (_a, 1));
do_strlen_word (get_word (_a, 2));
do_strlen_word (get_word (_a, 3));
do_strlen_word (get_word (_a, 4));
do_strlen_word (get_word (_a, 5));
do_strlen_word (get_word (_a, 6));
do_strlen_word (get_word (_a, 7));
do_strlen_word (get_word (_a, 8));
inc_ptr_as (unsigned long*, _a, 8);
}
}
while (1)
{
/* pull apart the last word processed and find the zero. */
bitfields_t bx;
bx.v = x;
#if __mips64
do_strlen_byte (0);
do_strlen_byte (1);
do_strlen_byte (2);
do_strlen_byte (3);
do_strlen_byte (4);
do_strlen_byte (5);
do_strlen_byte (6);
#else
do_strlen_byte (0);
do_strlen_byte (1);
do_strlen_byte (2);
#endif
/* last byte is zero */
break;
}
return cnt;
}
#undef do_strlen_byte
#undef do_strlen_word
#if SMOKE_TEST_MIPS_STRLEN
#include <stdio.h>
char str1[] = "DHRYSTONE PROGRAM, 1'ST STRING";
char str2[] = "DHRYSTONE PROGRAM, 2'ST STRING";
char str3[] = "another string";
char str4[] = "another";
char str5[] = "somes tring";
char str6[] = "somes_tring";
char str7[16], str8[16];
static char *
chk (unsigned long mine, unsigned long libs, int *errors)
{
static char answer[1024];
char *result = mine == libs ? "PASS" : "FAIL";
sprintf (answer, "new_strlen=%d: lib_strlen=%d: %s!", mine, libs, result);
if (mine != libs)
(*errors)++;
return answer;
}
int
main (int argc, char **argv)
{
int errors = 0;
/* set -1 in one position */
str6[5] = 0xff;
/* set zero in same position with junk in following 3 */
str7[0] = str8[0] = 0;
str7[1] = 0xff;
str7[2] = 'a';
str7[3] = 2;
str8[1] = 's';
str8[2] = -2;
str8[3] = 0;
fprintf (stderr, "========== mips_strlen%s test...\n",
argv[0] ? argv[0] : "unknown strlen");
#define P(__x,__y) {\
int a = my_strlen(__x + __y);\
int b = (strlen)(__x + __y) /* library version */;\
fprintf(stderr,"%s+%d: %s\n",#__x,__y,chk(a,b,&errors));\
}
P (str1, 0);
P (str1, 1);
P (str1, 2);
P (str1, 3);
P (str2, 0);
P (str2, 1);
P (str2, 2);
P (str2, 3);
P (str3, 0);
P (str3, 1);
P (str3, 2);
P (str3, 3);
P (str4, 0);
P (str4, 1);
P (str4, 2);
P (str4, 3);
P (str5, 0);
P (str5, 1);
P (str5, 2);
P (str5, 3);
P (str6, 0);
P (str6, 1);
P (str6, 2);
P (str6, 3);
P (str7, 0);
P (str7, 1);
P (str7, 2);
P (str7, 3);
P (str8, 0);
P (str8, 1);
P (str8, 2);
P (str8, 3);
return errors;
}
#endif

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___clock_nanosleep)
ENTRY(__clock_nanosleep)
.set push
.set noreorder
li v0, __NR_clock_nanosleep
@@ -22,5 +22,5 @@ ENTRY(___clock_nanosleep)
j t9
move ra, t0
.set pop
END(___clock_nanosleep)
.hidden ___clock_nanosleep
END(__clock_nanosleep)
.hidden __clock_nanosleep

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___fgetxattr)
ENTRY(fgetxattr)
.set push
.set noreorder
li v0, __NR_fgetxattr
@@ -22,5 +22,4 @@ ENTRY(___fgetxattr)
j t9
move ra, t0
.set pop
END(___fgetxattr)
.hidden ___fgetxattr
END(fgetxattr)

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___fsetxattr)
ENTRY(fsetxattr)
.set push
.set noreorder
li v0, __NR_fsetxattr
@@ -22,5 +22,4 @@ ENTRY(___fsetxattr)
j t9
move ra, t0
.set pop
END(___fsetxattr)
.hidden ___fsetxattr
END(fsetxattr)

View File

@@ -1,25 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(process_vm_readv)
.set push
.set noreorder
li v0, __NR_process_vm_readv
syscall
bnez a3, 1f
move a0, v0
j ra
nop
1:
move t0, ra
bal 2f
nop
2:
.cpsetup ra, t1, 2b
LA t9,__set_errno_internal
.cpreturn
j t9
move ra, t0
.set pop
END(process_vm_readv)

View File

@@ -1,25 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(process_vm_writev)
.set push
.set noreorder
li v0, __NR_process_vm_writev
syscall
bnez a3, 1f
move a0, v0
j ra
nop
1:
move t0, ra
bal 2f
nop
2:
.cpsetup ra, t1, 2b
LA t9,__set_errno_internal
.cpreturn
j t9
move ra, t0
.set pop
END(process_vm_writev)

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___clock_nanosleep)
ENTRY(__clock_nanosleep)
pushl %ebx
.cfi_def_cfa_offset 8
.cfi_rel_offset ebx, 0
@@ -33,5 +33,4 @@ ENTRY(___clock_nanosleep)
popl %ecx
popl %ebx
ret
END(___clock_nanosleep)
.hidden ___clock_nanosleep
END(__clock_nanosleep)

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___fgetxattr)
ENTRY(fgetxattr)
pushl %ebx
.cfi_def_cfa_offset 8
.cfi_rel_offset ebx, 0
@@ -33,5 +33,4 @@ ENTRY(___fgetxattr)
popl %ecx
popl %ebx
ret
END(___fgetxattr)
.hidden ___fgetxattr
END(fgetxattr)

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___fsetxattr)
ENTRY(fsetxattr)
pushl %ebx
.cfi_def_cfa_offset 8
.cfi_rel_offset ebx, 0
@@ -38,5 +38,4 @@ ENTRY(___fsetxattr)
popl %ecx
popl %ebx
ret
END(___fsetxattr)
.hidden ___fsetxattr
END(fsetxattr)

View File

@@ -1,46 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(process_vm_readv)
pushl %ebx
.cfi_def_cfa_offset 8
.cfi_rel_offset ebx, 0
pushl %ecx
.cfi_adjust_cfa_offset 4
.cfi_rel_offset ecx, 0
pushl %edx
.cfi_adjust_cfa_offset 4
.cfi_rel_offset edx, 0
pushl %esi
.cfi_adjust_cfa_offset 4
.cfi_rel_offset esi, 0
pushl %edi
.cfi_adjust_cfa_offset 4
.cfi_rel_offset edi, 0
pushl %ebp
.cfi_adjust_cfa_offset 4
.cfi_rel_offset ebp, 0
mov 28(%esp), %ebx
mov 32(%esp), %ecx
mov 36(%esp), %edx
mov 40(%esp), %esi
mov 44(%esp), %edi
mov 48(%esp), %ebp
movl $__NR_process_vm_readv, %eax
int $0x80
cmpl $-MAX_ERRNO, %eax
jb 1f
negl %eax
pushl %eax
call __set_errno_internal
addl $4, %esp
1:
popl %ebp
popl %edi
popl %esi
popl %edx
popl %ecx
popl %ebx
ret
END(process_vm_readv)

View File

@@ -1,46 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(process_vm_writev)
pushl %ebx
.cfi_def_cfa_offset 8
.cfi_rel_offset ebx, 0
pushl %ecx
.cfi_adjust_cfa_offset 4
.cfi_rel_offset ecx, 0
pushl %edx
.cfi_adjust_cfa_offset 4
.cfi_rel_offset edx, 0
pushl %esi
.cfi_adjust_cfa_offset 4
.cfi_rel_offset esi, 0
pushl %edi
.cfi_adjust_cfa_offset 4
.cfi_rel_offset edi, 0
pushl %ebp
.cfi_adjust_cfa_offset 4
.cfi_rel_offset ebp, 0
mov 28(%esp), %ebx
mov 32(%esp), %ecx
mov 36(%esp), %edx
mov 40(%esp), %esi
mov 44(%esp), %edi
mov 48(%esp), %ebp
movl $__NR_process_vm_writev, %eax
int $0x80
cmpl $-MAX_ERRNO, %eax
jb 1f
negl %eax
pushl %eax
call __set_errno_internal
addl $4, %esp
1:
popl %ebp
popl %edi
popl %esi
popl %edx
popl %ecx
popl %ebx
ret
END(process_vm_writev)

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___clock_nanosleep)
ENTRY(__clock_nanosleep)
movq %rcx, %r10
movl $__NR_clock_nanosleep, %eax
syscall
@@ -13,5 +13,5 @@ ENTRY(___clock_nanosleep)
call __set_errno_internal
1:
ret
END(___clock_nanosleep)
.hidden ___clock_nanosleep
END(__clock_nanosleep)
.hidden __clock_nanosleep

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___fgetxattr)
ENTRY(fgetxattr)
movq %rcx, %r10
movl $__NR_fgetxattr, %eax
syscall
@@ -13,5 +13,4 @@ ENTRY(___fgetxattr)
call __set_errno_internal
1:
ret
END(___fgetxattr)
.hidden ___fgetxattr
END(fgetxattr)

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(___fsetxattr)
ENTRY(fsetxattr)
movq %rcx, %r10
movl $__NR_fsetxattr, %eax
syscall
@@ -13,5 +13,4 @@ ENTRY(___fsetxattr)
call __set_errno_internal
1:
ret
END(___fsetxattr)
.hidden ___fsetxattr
END(fsetxattr)

View File

@@ -1,16 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(process_vm_readv)
movq %rcx, %r10
movl $__NR_process_vm_readv, %eax
syscall
cmpq $-MAX_ERRNO, %rax
jb 1f
negl %eax
movl %eax, %edi
call __set_errno_internal
1:
ret
END(process_vm_readv)

View File

@@ -1,16 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(process_vm_writev)
movq %rcx, %r10
movl $__NR_process_vm_writev, %eax
syscall
cmpq $-MAX_ERRNO, %rax
jb 1f
negl %eax
movl %eax, %edi
call __set_errno_internal
1:
ret
END(process_vm_writev)

View File

@@ -21,7 +21,6 @@
#include <stdlib.h>
#include <string.h>
#include "private/bionic_lock.h"
#include "private/bionic_systrace.h"
#include "private/libc_logging.h"
@@ -30,17 +29,12 @@
#define WRITE_OFFSET 32
constexpr char SYSTRACE_PROPERTY_NAME[] = "debug.atrace.tags.enableflags";
static Lock g_lock;
static const prop_info* g_pinfo;
static const prop_info* g_pinfo = NULL;
static uint32_t g_serial = -1;
static uint64_t g_tags;
static uint64_t g_tags = 0;
static int g_trace_marker_fd = -1;
static bool should_trace() {
bool result = false;
g_lock.lock();
// If g_pinfo is null, this means that systrace hasn't been run and it's safe to
// assume that no trace writing will need to take place. However, to avoid running
// this costly find check each time, we set it to a non-tracing value so that next
@@ -48,39 +42,32 @@ static bool should_trace() {
// this function also deals with the bootup case, during which the call to property
// set will fail if the property server hasn't yet started.
if (g_pinfo == NULL) {
g_pinfo = __system_property_find(SYSTRACE_PROPERTY_NAME);
g_pinfo = __system_property_find("debug.atrace.tags.enableflags");
if (g_pinfo == NULL) {
__system_property_set(SYSTRACE_PROPERTY_NAME, "0");
g_pinfo = __system_property_find(SYSTRACE_PROPERTY_NAME);
__system_property_set("debug.atrace.tags.enableflags", "0");
g_pinfo = __system_property_find("debug.atrace.tags.enableflags");
if (g_pinfo == NULL) {
return false;
}
}
}
if (g_pinfo != NULL) {
// Find out which tags have been enabled on the command line and set
// the value of tags accordingly. If the value of the property changes,
// the serial will also change, so the costly system_property_read function
// can be avoided by calling the much cheaper system_property_serial
// first. The values within pinfo may change, but its location is guaranteed
// not to move.
uint32_t cur_serial = __system_property_serial(g_pinfo);
if (cur_serial != g_serial) {
g_serial = cur_serial;
char value[PROP_VALUE_MAX];
__system_property_read(g_pinfo, 0, value);
g_tags = strtoull(value, NULL, 0);
}
result = ((g_tags & ATRACE_TAG_BIONIC) != 0);
}
g_lock.unlock();
return result;
}
static int get_trace_marker_fd() {
g_lock.lock();
if (g_trace_marker_fd == -1) {
g_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
// Find out which tags have been enabled on the command line and set
// the value of tags accordingly. If the value of the property changes,
// the serial will also change, so the costly system_property_read function
// can be avoided by calling the much cheaper system_property_serial
// first. The values within pinfo may change, but its location is guaranteed
// not to move.
const uint32_t cur_serial = __system_property_serial(g_pinfo);
if (cur_serial != g_serial) {
g_serial = cur_serial;
char value[PROP_VALUE_MAX];
__system_property_read(g_pinfo, 0, value);
g_tags = strtoull(value, NULL, 0);
}
g_lock.unlock();
return g_trace_marker_fd;
// Finally, verify that this tag value enables bionic tracing.
return ((g_tags & ATRACE_TAG_BIONIC) != 0);
}
ScopedTrace::ScopedTrace(const char* message) {
@@ -88,9 +75,11 @@ ScopedTrace::ScopedTrace(const char* message) {
return;
}
int trace_marker_fd = get_trace_marker_fd();
if (trace_marker_fd == -1) {
return;
if (g_trace_marker_fd == -1) {
g_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
if (g_trace_marker_fd == -1) {
__libc_fatal("Could not open kernel trace file: %s\n", strerror(errno));
}
}
// If bionic tracing has been enabled, then write the message to the
@@ -98,10 +87,12 @@ ScopedTrace::ScopedTrace(const char* message) {
int length = strlen(message);
char buf[length + WRITE_OFFSET];
size_t len = snprintf(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
ssize_t wbytes = TEMP_FAILURE_RETRY(write(g_trace_marker_fd, buf, len));
// Tracing may stop just after checking property and before writing the message.
// So the write is acceptable to fail. See b/20666100.
TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
// Error while writing
if (static_cast<size_t>(wbytes) != len) {
__libc_fatal("Could not write to kernel trace file: %s\n", strerror(errno));
}
}
ScopedTrace::~ScopedTrace() {
@@ -109,10 +100,10 @@ ScopedTrace::~ScopedTrace() {
return;
}
int trace_marker_fd = get_trace_marker_fd();
if (trace_marker_fd == -1) {
return;
}
ssize_t wbytes = TEMP_FAILURE_RETRY(write(g_trace_marker_fd, "E", 1));
TEMP_FAILURE_RETRY(write(trace_marker_fd, "E", 1));
// Error while writing
if (static_cast<size_t>(wbytes) != 1) {
__libc_fatal("Could not write to kernel trace file: %s\n", strerror(errno));
}
}

View File

@@ -30,9 +30,9 @@
#include "private/ErrnoRestorer.h"
extern "C" int ___clock_nanosleep(clockid_t, int, const timespec*, timespec*);
extern "C" int __clock_nanosleep(clockid_t, int, const timespec*, timespec*);
int clock_nanosleep(clockid_t clock_id, int flags, const timespec* in, timespec* out) {
ErrnoRestorer errno_restorer;
return (___clock_nanosleep(clock_id, flags, in, out) == 0) ? 0 : errno;
return (__clock_nanosleep(clock_id, flags, in, out) == 0) ? 0 : errno;
}

View File

@@ -27,7 +27,6 @@
*/
#include <ctype.h>
#include <elf.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
@@ -36,22 +35,14 @@
#include "debug_mapinfo.h"
#include "malloc_debug_disable.h"
#if defined(__LP64__)
#define Elf_W(x) Elf64_##x
#else
#define Elf_W(x) Elf32_##x
#endif
// Format of /proc/<PID>/maps:
// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /system/lib/libcomposer.so
static mapinfo_t* parse_maps_line(char* line) {
uintptr_t start;
uintptr_t end;
uintptr_t offset;
char permissions[4];
int name_pos;
if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %4s %" PRIxPTR " %*x:%*x %*d%n", &start,
&end, permissions, &offset, &name_pos) < 2) {
if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %*4s %*x %*x:%*x %*d%n", &start,
&end, &name_pos) < 2) {
return NULL;
}
@@ -68,14 +59,6 @@ static mapinfo_t* parse_maps_line(char* line) {
if (mi) {
mi->start = start;
mi->end = end;
mi->offset = offset;
if (permissions[0] != 'r') {
// Any unreadable map will just get a zero load base.
mi->load_base = 0;
mi->load_base_read = true;
} else {
mi->load_base_read = false;
}
memcpy(mi->name, name, name_len);
mi->name[name_len] = '\0';
}
@@ -112,58 +95,11 @@ __LIBC_HIDDEN__ void mapinfo_destroy(mapinfo_t* mi) {
}
}
template<typename T>
static inline bool get_val(mapinfo_t* mi, uintptr_t addr, T* store) {
if (addr < mi->start || addr + sizeof(T) > mi->end) {
return false;
}
// Make sure the address is aligned properly.
if (addr & (sizeof(T)-1)) {
return false;
}
*store = *reinterpret_cast<T*>(addr);
return true;
}
__LIBC_HIDDEN__ void mapinfo_read_loadbase(mapinfo_t* mi) {
mi->load_base = 0;
mi->load_base_read = true;
uintptr_t addr = mi->start;
Elf_W(Ehdr) ehdr;
if (!get_val<Elf_W(Half)>(mi, addr + offsetof(Elf_W(Ehdr), e_phnum), &ehdr.e_phnum)) {
return;
}
if (!get_val<Elf_W(Off)>(mi, addr + offsetof(Elf_W(Ehdr), e_phoff), &ehdr.e_phoff)) {
return;
}
addr += ehdr.e_phoff;
for (size_t i = 0; i < ehdr.e_phnum; i++) {
Elf_W(Phdr) phdr;
if (!get_val<Elf_W(Word)>(mi, addr + offsetof(Elf_W(Phdr), p_type), &phdr.p_type)) {
return;
}
if (!get_val<Elf_W(Off)>(mi, addr + offsetof(Elf_W(Phdr), p_offset), &phdr.p_offset)) {
return;
}
if (phdr.p_type == PT_LOAD && phdr.p_offset == mi->offset) {
if (!get_val<Elf_W(Addr)>(mi, addr + offsetof(Elf_W(Phdr), p_vaddr), &phdr.p_vaddr)) {
return;
}
mi->load_base = phdr.p_vaddr;
return;
}
addr += sizeof(phdr);
}
}
// Find the containing map info for the PC.
__LIBC_HIDDEN__ const mapinfo_t* mapinfo_find(mapinfo_t* mi, uintptr_t pc, uintptr_t* rel_pc) {
for (; mi != NULL; mi = mi->next) {
if ((pc >= mi->start) && (pc < mi->end)) {
if (!mi->load_base_read) {
mapinfo_read_loadbase(mi);
}
*rel_pc = pc - mi->start + mi->load_base;
*rel_pc = pc - mi->start;
return mi;
}
}

View File

@@ -35,9 +35,6 @@ struct mapinfo_t {
struct mapinfo_t* next;
uintptr_t start;
uintptr_t end;
uintptr_t offset;
uintptr_t load_base;
bool load_base_read;
char name[];
};

View File

@@ -41,19 +41,13 @@
extern "C" int __getdents64(unsigned int, dirent*, unsigned int);
// Apportable decided to copy the data structure from this file
// and use it in their own code, but they also call into readdir.
// In order to avoid a lockup, the structure must be maintained in
// the exact same order as in L and below. New structure members
// need to be added to the end of this structure.
// See b/21037208 for more details.
struct DIR {
int fd_;
size_t available_bytes_;
dirent* next_;
long current_pos_;
pthread_mutex_t mutex_;
dirent buff_[15];
long current_pos_;
};
static DIR* __allocate_DIR(int fd) {

View File

@@ -44,13 +44,11 @@
#define dlmalloc dlmalloc_real
#endif
/* These two symbols are exported on devices that use dlmalloc.
* In order to be consistent across all devices, they will
* be exported everywhere. Move the real symbols out of the way
* so that ndk_cruft.cpp can export these symbols.
*/
#define dlmalloc_inspect_all dlmalloc_inspect_all_real
#define dlmalloc_trim dlmalloc_trim_real
/* Export two symbols used by the VM. */
__BEGIN_DECLS
int dlmalloc_trim(size_t) __LIBC_ABI_PUBLIC__;
void dlmalloc_inspect_all(void (*handler)(void*, void*, size_t, void*), void*) __LIBC_ABI_PUBLIC__;
__END_DECLS
/* Include the proper definitions. */
#include "../upstream-dlmalloc/malloc.h"

View File

@@ -1,59 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/xattr.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
extern "C" int ___fsetxattr(int, const char*, const void*, size_t, int);
int fsetxattr(int fd, const char* name, const void* value, size_t size, int flags) {
int saved_errno = errno;
int result = ___fsetxattr(fd, name, value, size, flags);
if ((result == 0) || (errno != EBADF)) {
return result;
}
// fd could be an O_PATH file descriptor, and the kernel
// may not directly support fsetxattr() on such a file descriptor.
// Use /proc/self/fd instead to emulate this support.
int fd_flag = fcntl(fd, F_GETFL);
if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
errno = EBADF;
return -1;
}
char buf[40];
snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
errno = saved_errno;
return setxattr(buf, name, value, size, flags);
}

View File

@@ -18,14 +18,11 @@
#include <sys/cdefs.h>
#include <unistd.h>
#if !defined(__LP64__)
static_assert(sizeof(off_t) == 4,
"libc can't be built with _FILE_OFFSET_BITS=64.");
#if !defined(__USE_FILE_OFFSET64) && !defined(__LP64__)
// The kernel's implementation of ftruncate uses an unsigned long for the length
// parameter, so it will not catch negative values. On the other hand
// ftruncate64 does check for this, so just forward the call.
int ftruncate(int filedes, off_t length) {
return ftruncate64(filedes, length);
}
#endif // !defined(__LP64__)
#endif

View File

@@ -30,14 +30,11 @@
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/auxv.h>
#include <sys/personality.h>
#include <sys/time.h>
#include <unistd.h>
@@ -45,7 +42,6 @@
#include "private/bionic_ssp.h"
#include "private/bionic_tls.h"
#include "private/KernelArgumentBlock.h"
#include "private/libc_logging.h"
#include "pthread_internal.h"
extern "C" abort_msg_t** __abort_message_ptr;
@@ -124,213 +120,6 @@ void __libc_init_common(KernelArgumentBlock& args) {
__libc_init_vdso();
}
__noreturn static void __early_abort(int line) {
// We can't write to stdout or stderr because we're aborting before we've checked that
// it's safe for us to use those file descriptors. We probably can't strace either, so
// we rely on the fact that if we dereference a low address, either debuggerd or the
// kernel's crash dump will show the fault address.
*reinterpret_cast<int*>(line) = 0;
_exit(EXIT_FAILURE);
}
// Force any of the closed stdin, stdout and stderr to be associated with /dev/null.
static void __nullify_closed_stdio() {
int dev_null = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
if (dev_null == -1) {
// init won't have /dev/null available, but SELinux provides an equivalent.
dev_null = TEMP_FAILURE_RETRY(open("/sys/fs/selinux/null", O_RDWR));
}
if (dev_null == -1) {
__early_abort(__LINE__);
}
// If any of the stdio file descriptors is valid and not associated
// with /dev/null, dup /dev/null to it.
for (int i = 0; i < 3; i++) {
// If it is /dev/null already, we are done.
if (i == dev_null) {
continue;
}
// Is this fd already open?
int status = TEMP_FAILURE_RETRY(fcntl(i, F_GETFL));
if (status != -1) {
continue;
}
// The only error we allow is that the file descriptor does not
// exist, in which case we dup /dev/null to it.
if (errno == EBADF) {
// Try dupping /dev/null to this stdio file descriptor and
// repeat if there is a signal. Note that any errors in closing
// the stdio descriptor are lost.
status = TEMP_FAILURE_RETRY(dup2(dev_null, i));
if (status == -1) {
__early_abort(__LINE__);
}
} else {
__early_abort(__LINE__);
}
}
// If /dev/null is not one of the stdio file descriptors, close it.
if (dev_null > 2) {
if (close(dev_null) == -1) {
__early_abort(__LINE__);
}
}
}
// Check if the environment variable definition at 'envstr'
// starts with '<name>=', and if so return the address of the
// first character after the equal sign. Otherwise return null.
static const char* env_match(const char* envstr, const char* name) {
size_t i = 0;
while (envstr[i] == name[i] && name[i] != '\0') {
++i;
}
if (name[i] == '\0' && envstr[i] == '=') {
return envstr + i + 1;
}
return nullptr;
}
static bool __is_valid_environment_variable(const char* name) {
// According to the kernel source, by default the kernel uses 32*PAGE_SIZE
// as the maximum size for an environment variable definition.
const int MAX_ENV_LEN = 32*4096;
if (name == nullptr) {
return false;
}
// Parse the string, looking for the first '=' there, and its size.
int pos = 0;
int first_equal_pos = -1;
while (pos < MAX_ENV_LEN) {
if (name[pos] == '\0') {
break;
}
if (name[pos] == '=' && first_equal_pos < 0) {
first_equal_pos = pos;
}
pos++;
}
// Check that it's smaller than MAX_ENV_LEN (to detect non-zero terminated strings).
if (pos >= MAX_ENV_LEN) {
return false;
}
// Check that it contains at least one equal sign that is not the first character
if (first_equal_pos < 1) {
return false;
}
return true;
}
static bool __is_unsafe_environment_variable(const char* name) {
// None of these should be allowed in setuid programs.
static const char* const UNSAFE_VARIABLE_NAMES[] = {
"GCONV_PATH",
"GETCONF_DIR",
"HOSTALIASES",
"JE_MALLOC_CONF",
"LD_AOUT_LIBRARY_PATH",
"LD_AOUT_PRELOAD",
"LD_AUDIT",
"LD_DEBUG",
"LD_DEBUG_OUTPUT",
"LD_DYNAMIC_WEAK",
"LD_LIBRARY_PATH",
"LD_ORIGIN_PATH",
"LD_PRELOAD",
"LD_PROFILE",
"LD_SHOW_AUXV",
"LD_USE_LOAD_BIAS",
"LOCALDOMAIN",
"LOCPATH",
"MALLOC_CHECK_",
"MALLOC_CONF",
"MALLOC_TRACE",
"NIS_PATH",
"NLSPATH",
"RESOLV_HOST_CONF",
"RES_OPTIONS",
"TMPDIR",
"TZDIR",
nullptr
};
for (size_t i = 0; UNSAFE_VARIABLE_NAMES[i] != nullptr; ++i) {
if (env_match(name, UNSAFE_VARIABLE_NAMES[i]) != nullptr) {
return true;
}
}
return false;
}
static void __sanitize_environment_variables(char** env) {
bool is_AT_SECURE = getauxval(AT_SECURE);
char** src = env;
char** dst = env;
for (; src[0] != nullptr; ++src) {
if (!__is_valid_environment_variable(src[0])) {
continue;
}
// Remove various unsafe environment variables if we're loading a setuid program.
if (is_AT_SECURE && __is_unsafe_environment_variable(src[0])) {
continue;
}
dst[0] = src[0];
++dst;
}
dst[0] = nullptr;
}
static void __initialize_personality() {
#if !defined(__LP64__)
int old_value = personality(0xffffffff);
if (old_value == -1) {
__libc_fatal("error getting old personality value: %s", strerror(errno));
}
if (personality((static_cast<unsigned int>(old_value) & ~PER_MASK) | PER_LINUX32) == -1) {
__libc_fatal("error setting PER_LINUX32 personality: %s", strerror(errno));
}
#endif
}
void __libc_init_AT_SECURE(KernelArgumentBlock& args) {
__libc_auxv = args.auxv;
// Check that the kernel provided a value for AT_SECURE.
bool found_AT_SECURE = false;
for (ElfW(auxv_t)* v = __libc_auxv; v->a_type != AT_NULL; ++v) {
if (v->a_type == AT_SECURE) {
found_AT_SECURE = true;
break;
}
}
if (!found_AT_SECURE) __early_abort(__LINE__);
if (getauxval(AT_SECURE)) {
// If this is a setuid/setgid program, close the security hole described in
// ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-02:23.stdio.asc
__nullify_closed_stdio();
__sanitize_environment_variables(args.envp);
}
// Now the environment has been sanitized, make it available.
environ = args.envp;
__initialize_personality();
}
/* This function will be called during normal program termination
* to run the destructors that are listed in the .fini_array section
* of the executable, if any.

View File

@@ -49,12 +49,8 @@ __LIBC_HIDDEN__ void __libc_fini(void* finit_array);
__END_DECLS
#if defined(__cplusplus)
class KernelArgumentBlock;
__LIBC_HIDDEN__ void __libc_init_common(KernelArgumentBlock& args);
__LIBC_HIDDEN__ void __libc_init_AT_SECURE(KernelArgumentBlock& args);
#endif
#endif

View File

@@ -91,7 +91,6 @@ __noreturn void __libc_init(void* raw_args,
structors_array_t const * const structors) {
KernelArgumentBlock args(raw_args);
__libc_init_tls(args);
__libc_init_AT_SECURE(args);
__libc_init_common(args);
apply_gnu_relro();

View File

@@ -133,9 +133,8 @@ static HashEntry* record_backtrace(uintptr_t* backtrace, size_t numEntries, size
size |= SIZE_FLAG_ZYGOTE_CHILD;
}
// Keep the lock held for as little time as possible to prevent deadlocks.
ScopedPthreadMutexLocker locker(&g_hash_table->lock);
HashEntry* entry = find_entry(g_hash_table, slot, backtrace, numEntries, size);
if (entry != NULL) {
entry->allocations++;
} else {
@@ -303,6 +302,8 @@ extern "C" void* leak_malloc(size_t bytes) {
void* base = g_malloc_dispatch->malloc(size);
if (base != NULL) {
ScopedPthreadMutexLocker locker(&g_hash_table->lock);
uintptr_t backtrace[BACKTRACE_SIZE];
size_t numEntries = GET_BACKTRACE(backtrace, BACKTRACE_SIZE);
@@ -327,6 +328,8 @@ extern "C" void leak_free(void* mem) {
return;
}
ScopedPthreadMutexLocker locker(&g_hash_table->lock);
// check the guard to make sure it is valid
AllocationEntry* header = to_header(mem);
@@ -339,7 +342,6 @@ extern "C" void leak_free(void* mem) {
}
}
ScopedPthreadMutexLocker locker(&g_hash_table->lock);
if (header->guard == GUARD || is_valid_entry(header->entry)) {
// decrement the allocations
HashEntry* entry = header->entry;

View File

@@ -340,7 +340,7 @@ extern "C" pid_t __pthread_gettid(pthread_t t) {
return pthread_gettid_np(t);
}
// Older versions of apportable used dlmalloc directly instead of malloc,
// Older versions of appportable used dlmalloc directly instead of malloc,
// so export this compatibility shim that simply calls malloc.
extern "C" void* dlmalloc(size_t size) {
return malloc(size);
@@ -369,26 +369,3 @@ extern "C" void endusershell() { }
// This is never implemented in bionic, only needed for ABI compatibility with the NDK.
extern "C" void endpwent() { }
// Since dlmalloc_inspect_all and dlmalloc_trim are exported for systems
// that use dlmalloc, be consistent and export them everywhere.
#if defined(USE_JEMALLOC)
extern "C" void dlmalloc_inspect_all(void (*)(void*, void*, size_t, void*), void*) {
}
#else
extern "C" void dlmalloc_inspect_all_real(void (*)(void*, void*, size_t, void*), void*);
extern "C" void dlmalloc_inspect_all(void (*handler)(void*, void*, size_t, void*), void* arg) {
dlmalloc_inspect_all_real(handler, arg);
}
#endif
#if defined(USE_JEMALLOC)
extern "C" int dlmalloc_trim(size_t) {
return 0;
}
#else
extern "C" int dlmalloc_trim_real(size_t);
extern "C" int dlmalloc_trim(size_t pad) {
return dlmalloc_trim_real(pad);
}
#endif

View File

@@ -501,12 +501,6 @@ static int __pthread_mutex_lock_with_timeout(pthread_mutex_internal_t* mutex,
}
int pthread_mutex_lock(pthread_mutex_t* mutex_interface) {
#if !defined(__LP64__)
if (mutex_interface == NULL) {
return EINVAL;
}
#endif
pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
@@ -522,12 +516,6 @@ int pthread_mutex_lock(pthread_mutex_t* mutex_interface) {
}
int pthread_mutex_unlock(pthread_mutex_t* mutex_interface) {
#if !defined(__LP64__)
if (mutex_interface == NULL) {
return EINVAL;
}
#endif
pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);

View File

@@ -53,37 +53,10 @@ struct addrinfo;
#define __used_in_netd __attribute__((visibility ("default")))
/*
* A struct to capture context relevant to network operations.
*
* Application and DNS netids/marks can differ from one another under certain
* circumstances, notably when a VPN applies to the given uid's traffic but the
* VPN network does not have its own DNS servers explicitly provisioned.
*
* The introduction of per-UID routing means the uid is also an essential part
* of the evaluation context. Its proper uninitialized value is
* NET_CONTEXT_INVALID_UID.
*/
struct android_net_context {
unsigned app_netid;
unsigned app_mark;
unsigned dns_netid;
unsigned dns_mark;
uid_t uid;
} __attribute__((packed));
#define NET_CONTEXT_INVALID_UID ((uid_t)-1)
struct hostent *android_gethostbyaddrfornet(const void *, socklen_t, int, unsigned, unsigned) __used_in_netd;
struct hostent *android_gethostbynamefornet(const char *, int, unsigned, unsigned) __used_in_netd;
int android_getaddrinfofornet(const char *, const char *, const struct addrinfo *, unsigned,
unsigned, struct addrinfo **) __used_in_netd;
/*
* TODO: consider refactoring android_getaddrinfo_proxy() to serve as an
* explore_fqdn() dispatch table method, with the below function only making DNS calls.
*/
int android_getaddrinfofornetcontext(const char *, const char *, const struct addrinfo *,
const struct android_net_context *, struct addrinfo **) __used_in_netd;
unsigned, struct addrinfo **) __used_in_netd;
/* set name servers for a network */
extern void _resolv_set_nameservers_for_net(unsigned netid,

View File

@@ -218,7 +218,7 @@ struct res_target {
static int str2number(const char *);
static int explore_fqdn(const struct addrinfo *, const char *,
const char *, struct addrinfo **, const struct android_net_context *);
const char *, struct addrinfo **, unsigned netid, unsigned mark);
static int explore_null(const struct addrinfo *,
const char *, struct addrinfo **);
static int explore_numeric(const struct addrinfo *, const char *,
@@ -244,7 +244,6 @@ static void _endhtent(FILE **);
static struct addrinfo *_gethtent(FILE **, const char *,
const struct addrinfo *);
static int _files_getaddrinfo(void *, void *, va_list);
static int _find_src_addr(const struct sockaddr *, struct sockaddr *, unsigned , uid_t);
static int res_queryN(const char *, struct res_target *, res_state);
static int res_searchN(const char *, struct res_target *, res_state);
@@ -360,6 +359,29 @@ str2number(const char *p)
return -1;
}
/*
* Connect a UDP socket to a given unicast address. This will cause no network
* traffic, but will fail fast if the system has no or limited reachability to
* the destination (e.g., no IPv4 address, no IPv6 default route, ...).
*/
static int
_test_connect(int pf, struct sockaddr *addr, size_t addrlen, unsigned mark) {
int s = socket(pf, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
if (s < 0)
return 0;
if (mark != MARK_UNSET && setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
return 0;
int ret;
do {
ret = __connect(s, addr, addrlen);
} while (ret < 0 && errno == EINTR);
int success = (ret == 0);
do {
ret = close(s);
} while (ret < 0 && errno == EINTR);
return success;
}
/*
* The following functions determine whether IPv4 or IPv6 connectivity is
* available in order to implement AI_ADDRCONFIG.
@@ -370,24 +392,24 @@ str2number(const char *p)
* so checking for connectivity is the next best thing.
*/
static int
_have_ipv6(unsigned mark, uid_t uid) {
_have_ipv6(unsigned mark) {
static const struct sockaddr_in6 sin6_test = {
.sin6_family = AF_INET6,
.sin6_addr.s6_addr = { // 2000::
0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
sockaddr_union addr = { .in6 = sin6_test };
return _find_src_addr(&addr.generic, NULL, mark, uid) == 1;
return _test_connect(PF_INET6, &addr.generic, sizeof(addr.in6), mark);
}
static int
_have_ipv4(unsigned mark, uid_t uid) {
_have_ipv4(unsigned mark) {
static const struct sockaddr_in sin_test = {
.sin_family = AF_INET,
.sin_addr.s_addr = __constant_htonl(0x08080808L) // 8.8.8.8
};
sockaddr_union addr = { .in = sin_test };
return _find_src_addr(&addr.generic, NULL, mark, uid) == 1;
return _test_connect(PF_INET, &addr.generic, sizeof(addr.in), mark);
}
bool readBE32(FILE* fp, int32_t* result) {
@@ -452,7 +474,7 @@ android_getaddrinfo_proxy(
int result_code = (int)strtol(buf, NULL, 10);
// verify the code itself
if (result_code != DnsProxyQueryResult) {
if (result_code != DnsProxyQueryResult ) {
fread(buf, 1, sizeof(buf), proxy);
goto exit;
}
@@ -566,21 +588,6 @@ getaddrinfo(const char *hostname, const char *servname,
int
android_getaddrinfofornet(const char *hostname, const char *servname,
const struct addrinfo *hints, unsigned netid, unsigned mark, struct addrinfo **res)
{
struct android_net_context netcontext = {
.app_netid = netid,
.app_mark = mark,
.dns_netid = netid,
.dns_mark = mark,
.uid = NET_CONTEXT_INVALID_UID,
};
return android_getaddrinfofornetcontext(hostname, servname, hints, &netcontext, res);
}
int
android_getaddrinfofornetcontext(const char *hostname, const char *servname,
const struct addrinfo *hints, const struct android_net_context *netcontext,
struct addrinfo **res)
{
struct addrinfo sentinel;
struct addrinfo *cur;
@@ -594,7 +601,6 @@ android_getaddrinfofornetcontext(const char *hostname, const char *servname,
/* servname is allowed to be NULL */
/* hints is allowed to be NULL */
assert(res != NULL);
assert(netcontext != NULL);
memset(&sentinel, 0, sizeof(sentinel));
cur = &sentinel;
pai = &ai;
@@ -725,8 +731,7 @@ android_getaddrinfofornetcontext(const char *hostname, const char *servname,
ERR(EAI_NONAME);
#if defined(__ANDROID__)
int gai_error = android_getaddrinfo_proxy(
hostname, servname, hints, res, netcontext->app_netid);
int gai_error = android_getaddrinfo_proxy(hostname, servname, hints, res, netid);
if (gai_error != EAI_SYSTEM) {
return gai_error;
}
@@ -758,8 +763,8 @@ android_getaddrinfofornetcontext(const char *hostname, const char *servname,
if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
pai->ai_protocol = ex->e_protocol;
error = explore_fqdn(
pai, hostname, servname, &cur->ai_next, netcontext);
error = explore_fqdn(pai, hostname, servname,
&cur->ai_next, netid, mark);
while (cur && cur->ai_next)
cur = cur->ai_next;
@@ -792,8 +797,7 @@ android_getaddrinfofornetcontext(const char *hostname, const char *servname,
*/
static int
explore_fqdn(const struct addrinfo *pai, const char *hostname,
const char *servname, struct addrinfo **res,
const struct android_net_context *netcontext)
const char *servname, struct addrinfo **res, unsigned netid, unsigned mark)
{
struct addrinfo *result;
struct addrinfo *cur;
@@ -819,7 +823,7 @@ explore_fqdn(const struct addrinfo *pai, const char *hostname,
return 0;
switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
default_dns_files, hostname, pai, netcontext)) {
default_dns_files, hostname, pai, netid, mark)) {
case NS_TRYAGAIN:
error = EAI_AGAIN;
goto free;
@@ -1759,13 +1763,13 @@ _rfc6724_compare(const void *ptr1, const void* ptr2)
* address. src_addr must be large enough to hold a struct sockaddr_in6.
*
* Returns 1 if a source address was found, 0 if the address is unreachable,
* and -1 if a fatal error occurred. If 0 or -1, the contents of src_addr are
* and -1 if a fatal error occurred. If 0 or 1, the contents of src_addr are
* undefined.
*/
/*ARGSUSED*/
static int
_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned mark, uid_t uid)
_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned mark)
{
int sock;
int ret;
@@ -1793,8 +1797,6 @@ _find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned
}
if (mark != MARK_UNSET && setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
return 0;
if (uid > 0 && uid != NET_CONTEXT_INVALID_UID && fchown(sock, uid, (gid_t)-1) < 0)
return 0;
do {
ret = __connect(sock, addr, len);
} while (ret == -1 && errno == EINTR);
@@ -1804,7 +1806,7 @@ _find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned
return 0;
}
if (src_addr && getsockname(sock, src_addr, &len) == -1) {
if (getsockname(sock, src_addr, &len) == -1) {
close(sock);
return -1;
}
@@ -1819,7 +1821,7 @@ _find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned
/*ARGSUSED*/
static void
_rfc6724_sort(struct addrinfo *list_sentinel, unsigned mark, uid_t uid)
_rfc6724_sort(struct addrinfo *list_sentinel, unsigned mark)
{
struct addrinfo *cur;
int nelem = 0, i;
@@ -1846,7 +1848,7 @@ _rfc6724_sort(struct addrinfo *list_sentinel, unsigned mark, uid_t uid)
elems[i].ai = cur;
elems[i].original_order = i;
has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic, mark, uid);
has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic, mark);
if (has_src_addr == -1) {
goto error;
}
@@ -1877,11 +1879,12 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
struct addrinfo sentinel, *cur;
struct res_target q, q2;
res_state res;
const struct android_net_context *netcontext;
unsigned netid, mark;
name = va_arg(ap, char *);
pai = va_arg(ap, const struct addrinfo *);
netcontext = va_arg(ap, const struct android_net_context *);
netid = va_arg(ap, unsigned);
mark = va_arg(ap, unsigned);
//fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name);
memset(&q, 0, sizeof(q));
@@ -1910,8 +1913,8 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
q.anslen = sizeof(buf->buf);
int query_ipv6 = 1, query_ipv4 = 1;
if (pai->ai_flags & AI_ADDRCONFIG) {
query_ipv6 = _have_ipv6(netcontext->app_mark, netcontext->uid);
query_ipv4 = _have_ipv4(netcontext->app_mark, netcontext->uid);
query_ipv6 = _have_ipv6(mark);
query_ipv4 = _have_ipv4(mark);
}
if (query_ipv6) {
q.qtype = T_AAAA;
@@ -1963,8 +1966,8 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
* fully populate the thread private data here, but if we get down there
* and have a cache hit that would be wasted, so we do the rest there on miss
*/
res_setnetid(res, netcontext->dns_netid);
res_setmark(res, netcontext->dns_mark);
res_setnetid(res, netid);
res_setmark(res, mark);
if (res_searchN(name, &q, res) < 0) {
__res_put_state(res);
free(buf);
@@ -1996,7 +1999,7 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
}
}
_rfc6724_sort(&sentinel, netcontext->app_mark, netcontext->uid);
_rfc6724_sort(&sentinel, netid);
__res_put_state(res);

View File

@@ -640,9 +640,6 @@ android_read_hostent(FILE* proxy, struct hostent* hp, char* hbuf, size_t hbuflen
ptr += size;
}
// Fix alignment after variable-length data.
ptr = (char*)ALIGN(ptr);
int aliases_len = ((int)(aliases - aliases_ptrs) + 1) * sizeof(*hp->h_aliases);
if (ptr + aliases_len > hbuf_end) {
goto nospc;
@@ -677,9 +674,6 @@ android_read_hostent(FILE* proxy, struct hostent* hp, char* hbuf, size_t hbuflen
ptr += size;
}
// Fix alignment after variable-length data.
ptr = (char*)ALIGN(ptr);
int addrs_len = ((int)(addr_p - addr_ptrs) + 1) * sizeof(*hp->h_addr_list);
if (ptr + addrs_len > hbuf_end) {
goto nospc;

View File

@@ -73,13 +73,6 @@ enum {
*/
ANDROID_DLEXT_FORCE_LOAD = 0x40,
/* When set, if the minimum p_vaddr of the ELF file's PT_LOAD segments is non-zero,
* the dynamic linker will load it at that address.
*
* This flag is for ART internal use only.
*/
ANDROID_DLEXT_FORCE_FIXED_VADDR = 0x80,
/* Mask of valid bits */
ANDROID_DLEXT_VALID_FLAG_BITS = ANDROID_DLEXT_RESERVED_ADDRESS |
ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
@@ -87,8 +80,7 @@ enum {
ANDROID_DLEXT_USE_RELRO |
ANDROID_DLEXT_USE_LIBRARY_FD |
ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET |
ANDROID_DLEXT_FORCE_LOAD |
ANDROID_DLEXT_FORCE_FIXED_VADDR,
ANDROID_DLEXT_FORCE_LOAD,
};
typedef struct {

View File

@@ -176,18 +176,10 @@ int pthread_mutexattr_settype(pthread_mutexattr_t*, int) __nonnull((1));
int pthread_mutex_destroy(pthread_mutex_t*) __nonnull((1));
int pthread_mutex_init(pthread_mutex_t*, const pthread_mutexattr_t*) __nonnull((1));
#if !defined(__LP64__)
int pthread_mutex_lock(pthread_mutex_t*) /* __nonnull((1)) */;
#else
int pthread_mutex_lock(pthread_mutex_t*) __nonnull((1));
#endif
int pthread_mutex_timedlock(pthread_mutex_t*, const struct timespec*) __nonnull((1, 2));
int pthread_mutex_trylock(pthread_mutex_t*) __nonnull((1));
#if !defined(__LP4__)
int pthread_mutex_unlock(pthread_mutex_t*) /* __nonnull((1)) */;
#else
int pthread_mutex_unlock(pthread_mutex_t*) __nonnull((1));
#endif
int pthread_once(pthread_once_t*, void (*)(void)) __nonnull((1, 2));

View File

@@ -34,7 +34,7 @@
__BEGIN_DECLS
extern int personality (unsigned int persona);
extern int personality (unsigned long persona);
__END_DECLS

View File

@@ -34,31 +34,11 @@
__BEGIN_DECLS
/* glibc uses different PTRACE_ names from the kernel for these two... */
/* glibc uses different names from the kernel for these two... */
#define PTRACE_POKEUSER PTRACE_POKEUSR
#define PTRACE_PEEKUSER PTRACE_PEEKUSR
/* glibc exports a different set of PT_ names too... */
#define PT_TRACE_ME PTRACE_TRACEME
#define PT_READ_I PTRACE_PEEKTEXT
#define PT_READ_D PTRACE_PEEKDATA
#define PT_READ_U PTRACE_PEEKUSR
#define PT_WRITE_I PTRACE_POKETEXT
#define PT_WRITE_D PTRACE_POKEDATA
#define PT_WRITE_U PTRACE_POKEUSR
#define PT_CONT PTRACE_CONT
#define PT_KILL PTRACE_KILL
#define PT_STEP PTRACE_SINGLESTEP
#define PT_GETFPREGS PTRACE_GETFPREGS
#define PT_ATTACH PTRACE_ATTACH
#define PT_DETACH PTRACE_DETACH
#define PT_SYSCALL PTRACE_SYSCALL
#define PT_SETOPTIONS PTRACE_SETOPTIONS
#define PT_GETEVENTMSG PTRACE_GETEVENTMSG
#define PT_GETSIGINFO PTRACE_GETSIGINFO
#define PT_SETSIGINFO PTRACE_SETSIGINFO
long ptrace(int, ...);
extern long ptrace(int, ...);
__END_DECLS

View File

@@ -59,7 +59,6 @@ enum {
typedef int greg_t;
typedef greg_t gregset_t[NGREG];
typedef struct user_fpregs fpregset_t;
#include <asm/sigcontext.h>
typedef struct sigcontext mcontext_t;
@@ -83,13 +82,6 @@ typedef struct ucontext {
typedef unsigned long greg_t;
typedef greg_t gregset_t[NGREG];
struct user_fpsimd_struct {
long double vregs[32];
uint32_t fpsr;
uint32_t fpcr;
};
typedef struct user_fpsimd_struct fpregset_t;
#include <asm/sigcontext.h>
typedef struct sigcontext mcontext_t;

View File

@@ -34,13 +34,8 @@
__BEGIN_DECLS
int readv(int, const struct iovec*, int);
int writev(int, const struct iovec*, int);
#if defined(__USE_GNU)
ssize_t process_vm_readv(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long);
ssize_t process_vm_writev(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long);
#endif
int readv(int, const struct iovec *, int);
int writev(int, const struct iovec *, int);
__END_DECLS

View File

@@ -45,9 +45,6 @@ __BEGIN_DECLS
#define WIFSTOPPED(s) (WTERMSIG(s) == 0x7f)
#define WIFSIGNALED(s) (WTERMSIG((s)+1) >= 2)
#define W_EXITCODE(ret, sig) ((ret) << 8 | (sig))
#define W_STOPCODE(sig) ((sig) << 8 | 0x7f)
extern pid_t wait(int *);
extern pid_t waitpid(pid_t, int *, int);
extern pid_t wait4(pid_t, int *, int, struct rusage *);

View File

@@ -34,6 +34,11 @@
__BEGIN_DECLS
#if defined(__GNUC__) && __GNUC__ >= 5 && !defined(__cplusplus)
typedef __CHAR16_TYPE__ char16_t;
typedef __CHAR32_TYPE__ char32_t;
#endif
#define __STD_UTF_16__ 1
#define __STD_UTF_32__ 1

File diff suppressed because it is too large Load Diff

View File

@@ -37,18 +37,7 @@
#include "atexit.h"
#include "private/thread_private.h"
struct atexit {
struct atexit *next; /* next in list */
int ind; /* next index in this table */
int max; /* max entries >= ATEXIT_SIZE */
struct atexit_fn {
void (*fn_ptr)(void *);
void *fn_arg; /* argument for CXA callback */
void *fn_dso; /* shared module handle */
} fns[1]; /* the table itself */
};
static struct atexit *__atexit;
struct atexit *__atexit;
static int restartloop;
/* BEGIN android-changed: __unregister_atfork is used by __cxa_finalize */

View File

@@ -30,5 +30,18 @@
*
*/
struct atexit {
struct atexit *next; /* next in list */
int ind; /* next index in this table */
int max; /* max entries >= ATEXIT_SIZE */
struct atexit_fn {
void (*fn_ptr)(void *);
void *fn_arg; /* argument for CXA callback */
void *fn_dso; /* shared module handle */
} fns[1]; /* the table itself */
};
extern struct atexit *__atexit; /* points to head of LIFO stack */
int __cxa_atexit(void (*)(void *), void *, void *);
void __cxa_finalize(void *);

View File

@@ -13,9 +13,21 @@ arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain)
sys.stderr.write('Checking symbols for arch "%s"...\n' % arch)
def GetSymbols(library, functions_or_variables):
global api
global arch
api = '9'
if library == 'libm' and arch == 'arm':
api = '3'
# There were no 64-bit ABIs before API level 21.
if '64' in arch:
api = '21'
# What GCC calls aarch64, Android calls arm64.
if arch == 'aarch64':
arch = 'arm64'
path = '%s/development/ndk/platforms/android-%s/arch-%s/symbols/%s.so.%s.txt' % (os.environ['ANDROID_BUILD_TOP'], api, arch, library, functions_or_variables)
symbols = set()
for line in open(path, 'r'):
@@ -26,7 +38,11 @@ def GetSymbols(library, functions_or_variables):
def CheckSymbols(library, functions_or_variables):
expected_symbols = GetSymbols(library, functions_or_variables)
so_file = '%s/system/lib/%s.so' % (os.environ['ANDROID_PRODUCT_OUT'], library)
lib_dir = 'lib'
if '64' in arch:
lib_dir = 'lib64'
so_file = '%s/system/%s/%s.so' % (os.environ['ANDROID_PRODUCT_OUT'], lib_dir, library)
# Example readelf output:
# 264: 0001623c 4 FUNC GLOBAL DEFAULT 8 cabsf
@@ -38,14 +54,13 @@ def CheckSymbols(library, functions_or_variables):
r = re.compile(r' +\d+: [0-9a-f]+ +\d+ (FUNC|OBJECT) +\S+ +\S+ +\d+ (\S+)')
actual_symbols = set()
for line in subprocess.check_output(['readelf', '--dyn-syms', so_file]).split('\n'):
for line in subprocess.check_output(['readelf', '-W', '--dyn-syms', so_file]).split('\n'):
m = r.match(line)
if m:
symbol = string.split(m.group(2), '@')[0]
if m.group(1) == 'FUNC' and functions_or_variables == 'functions':
actual_symbols.add(symbol)
actual_symbols.add(m.group(2))
elif m.group(1) == 'OBJECT' and functions_or_variables == 'variables':
actual_symbols.add(symbol)
actual_symbols.add(m.group(2))
#else:
#print 'ignoring: ' % line
@@ -55,6 +70,12 @@ def CheckSymbols(library, functions_or_variables):
for miss in sorted(missing):
sys.stderr.write(' %s\n' % miss)
extra = actual_symbols - expected_symbols
if len(extra) > 0:
sys.stderr.write('%d extra %s in %s for %s:\n' % (len(extra), functions_or_variables, library, arch))
for s in sorted(extra):
sys.stderr.write(' %s\n' % s)
return len(missing) == 0
CheckSymbols("libc", "functions")

View File

@@ -74,6 +74,7 @@ __LIBC_HIDDEN__ void* reallocarray(void*, size_t, size_t);
__LIBC64_HIDDEN__ extern const short* _tolower_tab_;
__LIBC64_HIDDEN__ extern const short* _toupper_tab_;
__LIBC_HIDDEN__ extern struct atexit* __atexit;
__LIBC_HIDDEN__ extern const char _C_ctype_[];
__LIBC_HIDDEN__ extern const short _C_toupper_[];
__LIBC_HIDDEN__ extern const short _C_tolower_[];

Binary file not shown.

View File

@@ -501,9 +501,6 @@ LOCAL_CFLAGS += \
-fno-builtin-rintf \
-fno-builtin-rintl \
LOCAL_CONLY_FLAGS := \
-std=c99 \
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
LOCAL_ADDRESS_SANITIZER := false
include $(BUILD_STATIC_LIBRARY)
@@ -513,14 +510,10 @@ include $(BUILD_STATIC_LIBRARY)
# -----------------------------------------------------------------------------
include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/libm.map
# TODO: This is to work around b/19059885. Remove after root cause is fixed
LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/libm.map
LOCAL_MODULE := libm
LOCAL_CLANG := $(libm_clang)
LOCAL_SYSTEM_SHARED_LIBRARIES := libc

View File

@@ -1,378 +0,0 @@
LIBC {
global:
__fe_dfl_env;
__signbit;
__signbitf;
__signbitl;
acos;
acosf;
acosh;
acoshf;
acoshl;
acosl;
asin;
asinf;
asinh;
asinhf;
asinhl;
asinl;
atan;
atan2;
atan2f;
atan2l;
atanf;
atanh;
atanhf;
atanhl;
atanl;
cabs;
cabsf;
cabsl;
cacos;
cacosf;
cacosh;
cacoshf;
carg;
cargf;
cargl;
casin;
casinf;
casinh;
casinhf;
catan;
catanf;
catanh;
catanhf;
cbrt;
cbrtf;
cbrtl;
ccos;
ccosf;
ccosh;
ccoshf;
ceil;
ceilf;
ceill;
cexp;
cexpf;
cimag;
cimagf;
cimagl;
conj;
conjf;
conjl;
copysign;
copysignf;
copysignl;
cos;
cosf;
cosh;
coshf;
coshl;
cosl;
cproj;
cprojf;
cprojl;
creal;
crealf;
creall;
csin;
csinf;
csinh;
csinhf;
csqrt;
csqrtf;
csqrtl;
ctan;
ctanf;
ctanh;
ctanhf;
drem;
dremf;
erf;
erfc;
erfcf;
erfcl;
erff;
erfl;
exp;
exp2;
exp2f;
exp2l;
expf;
expl;
expm1;
expm1f;
expm1l;
fabs;
fabsf;
fabsl;
fdim;
fdimf;
fdiml;
feclearexcept;
fedisableexcept;
feenableexcept;
fegetenv;
fegetexcept;
fegetexceptflag;
fegetround;
feholdexcept;
feraiseexcept;
fesetenv;
fesetexceptflag;
fesetround;
fetestexcept;
feupdateenv;
finite;
finitef;
floor;
floorf;
floorl;
fma;
fmaf;
fmal;
fmax;
fmaxf;
fmaxl;
fmin;
fminf;
fminl;
fmod;
fmodf;
fmodl;
frexp;
frexpf;
frexpl;
gamma;
gamma_r;
gammaf;
gammaf_r;
hypot;
hypotf;
hypotl;
ilogb;
ilogbf;
ilogbl;
j0;
j0f;
j1;
j1f;
jn;
jnf;
ldexpf;
ldexpl;
lgamma;
lgamma_r;
lgammaf;
lgammaf_r;
lgammal;
lgammal_r;
llrint;
llrintf;
llrintl;
llround;
llroundf;
llroundl;
log;
log10;
log10f;
log10l;
log1p;
log1pf;
log1pl;
log2;
log2f;
log2l;
logb;
logbf;
logbl;
logf;
logl;
lrint;
lrintf;
lrintl;
lround;
lroundf;
lroundl;
modf;
modff;
modfl;
nan;
nanf;
nanl;
nearbyint;
nearbyintf;
nearbyintl;
nextafter;
nextafterf;
nextafterl;
nexttoward;
nexttowardf;
nexttowardl;
pow;
powf;
powl;
remainder;
remainderf;
remainderl;
remquo;
remquof;
remquol;
rint;
rintf;
rintl;
round;
roundf;
roundl;
scalb;
scalbf;
scalbln;
scalblnf;
scalblnl;
scalbn;
scalbnf;
scalbnl;
signgam;
significand;
significandf;
significandl;
sin;
sincos;
sincosf;
sincosl;
sinf;
sinh;
sinhf;
sinhl;
sinl;
sqrt;
sqrtf;
sqrtl;
tan;
tanf;
tanh;
tanhf;
tanhl;
tanl;
tgamma;
tgammaf;
tgammal;
trunc;
truncf;
truncl;
y0;
y0f;
y1;
y1f;
yn;
ynf;
local:
*;
};
LIBC_PRIVATE {
global:
___Unwind_Backtrace; # arm
___Unwind_ForcedUnwind; # arm
___Unwind_RaiseException; # arm
___Unwind_Resume; # arm
___Unwind_Resume_or_Rethrow; # arm
__adddf3; # arm
__aeabi_cdcmpeq; # arm
__aeabi_cdcmple; # arm
__aeabi_cdrcmple; # arm
__aeabi_cfcmpeq; # arm
__aeabi_cfcmple; # arm
__aeabi_cfrcmple; # arm
__aeabi_d2lz; # arm
__aeabi_d2uiz; # arm
__aeabi_d2ulz; # arm
__aeabi_dadd; # arm
__aeabi_dcmpeq; # arm
__aeabi_dcmpge; # arm
__aeabi_dcmpgt; # arm
__aeabi_dcmple; # arm
__aeabi_dcmplt; # arm
__aeabi_ddiv; # arm
__aeabi_dmul; # arm
__aeabi_drsub; # arm
__aeabi_dsub; # arm
__aeabi_f2d; # arm
__aeabi_f2lz; # arm
__aeabi_f2ulz; # arm
__aeabi_fcmpeq; # arm
__aeabi_fcmpge; # arm
__aeabi_fcmpgt; # arm
__aeabi_fcmple; # arm
__aeabi_fcmplt; # arm
__aeabi_i2d; # arm
__aeabi_l2d; # arm
__aeabi_ui2d; # arm
__aeabi_ul2d; # arm
__aeabi_unwind_cpp_pr0; # arm
__aeabi_unwind_cpp_pr1; # arm
__aeabi_unwind_cpp_pr2; # arm
__cmpdf2; # arm
__cmpsf2; # arm
__divdf3; # arm
__eqdf2; # arm
__eqsf2; # arm
__extendsfdf2; # arm
__fixdfdi; # arm mips
__fixsfdi; # arm mips
__fixunsdfdi; # arm mips
__fixunsdfsi; # arm
__fixunssfdi; # arm mips
__floatdidf; # arm
__floatsidf; # arm
__floatundidf; # arm
__floatunsidf; # arm
__gedf2; # arm
__gesf2; # arm
__gnu_Unwind_Backtrace; # arm
__gnu_unwind_execute; # arm
__gnu_Unwind_ForcedUnwind; # arm
__gnu_unwind_frame; # arm
__gnu_Unwind_RaiseException; # arm
__gnu_Unwind_Restore_VFP; # arm
__gnu_Unwind_Restore_VFP_D; # arm
__gnu_Unwind_Restore_VFP_D_16_to_31; # arm
__gnu_Unwind_Restore_WMMXC; # arm
__gnu_Unwind_Restore_WMMXD; # arm
__gnu_Unwind_Resume; # arm
__gnu_Unwind_Resume_or_Rethrow; # arm
__gnu_Unwind_Save_VFP; # arm
__gnu_Unwind_Save_VFP_D; # arm
__gnu_Unwind_Save_VFP_D_16_to_31; # arm
__gnu_Unwind_Save_WMMXC; # arm
__gnu_Unwind_Save_WMMXD; # arm
__gtdf2; # arm
__gtsf2; # arm
__ledf2; # arm
__lesf2; # arm
__ltdf2; # arm
__ltsf2; # arm
__muldc3; # arm x86 mips
__muldf3; # arm
__nedf2; # arm
__nesf2; # arm
__restore_core_regs; # arm
__subdf3; # arm
_Unwind_Backtrace; # arm
_Unwind_Complete; # arm
_Unwind_DeleteException; # arm
_Unwind_ForcedUnwind; # arm
_Unwind_GetCFA; # arm
_Unwind_GetDataRelBase; # arm
_Unwind_GetLanguageSpecificData; # arm
_Unwind_GetRegionStart; # arm
_Unwind_GetTextRelBase; # arm
_Unwind_RaiseException; # arm
_Unwind_Resume; # arm
_Unwind_Resume_or_Rethrow; # arm
_Unwind_VRS_Get; # arm
_Unwind_VRS_Pop; # arm
_Unwind_VRS_Set; # arm
restore_core_regs; # arm
} LIBC;

View File

@@ -9,6 +9,7 @@ LOCAL_SRC_FILES:= \
linker_allocator.cpp \
linker_sdk_versions.cpp \
linker_block_allocator.cpp \
linker_environ.cpp \
linker_libc_support.c \
linker_memory.cpp \
linker_phdr.cpp \

View File

@@ -22,7 +22,6 @@
#include <stdlib.h>
#include <string.h>
#include <android/dlext.h>
#include <android/api-level.h>
#include <bionic/pthread_internal.h>
#include "private/bionic_tls.h"
@@ -158,14 +157,7 @@ int dlclose(void* handle) {
return 0;
}
int dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data) {
ScopedPthreadMutexLocker locker(&g_dl_mutex);
return do_dl_iterate_phdr(cb, data);
}
void android_set_application_target_sdk_version(uint32_t target) {
// lock to avoid modification in the middle of dlopen.
ScopedPthreadMutexLocker locker(&g_dl_mutex);
set_application_target_sdk_version(target);
}
@@ -266,7 +258,6 @@ soinfo* get_libdl_info() {
__libdl_info->strtab_size_ = sizeof(ANDROID_LIBDL_STRTAB);
__libdl_info->local_group_root_ = __libdl_info;
__libdl_info->soname_ = "libdl.so";
__libdl_info->target_sdk_version_ = __ANDROID_API__;
#if defined(__arm__)
strlcpy(__libdl_info->old_name_, __libdl_info->soname_, sizeof(__libdl_info->old_name_));
#endif

View File

@@ -26,7 +26,6 @@
* SUCH DAMAGE.
*/
#include <android/api-level.h>
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
@@ -37,6 +36,7 @@
#include <string.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <sys/personality.h>
#include <unistd.h>
#include <new>
@@ -53,15 +53,14 @@
#include "linker.h"
#include "linker_block_allocator.h"
#include "linker_debug.h"
#include "linker_environ.h"
#include "linker_sleb128.h"
#include "linker_phdr.h"
#include "linker_relocs.h"
#include "linker_reloc_iterators.h"
#include "ziparchive/zip_archive.h"
extern void __libc_init_AT_SECURE(KernelArgumentBlock&);
// Override macros to use C++ style casts.
// Override macros to use C++ style casts
#undef ELF_ST_TYPE
#define ELF_ST_TYPE(x) (static_cast<uint32_t>(x) & 0xf)
@@ -277,7 +276,6 @@ static void soinfo_free(soinfo* si) {
sonext = prev;
}
si->~soinfo();
g_soinfo_allocator.free(si);
}
@@ -318,7 +316,6 @@ static bool realpath_fd(int fd, std::string* realpath) {
std::vector<char> buf(PATH_MAX), proc_self_fd(PATH_MAX);
snprintf(&proc_self_fd[0], proc_self_fd.size(), "/proc/self/fd/%d", fd);
if (readlink(&proc_self_fd[0], &buf[0], buf.size()) == -1) {
PRINT("readlink('%s') failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd);
return false;
}
@@ -353,7 +350,7 @@ _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) {
// Here, we only have to provide a callback to iterate across all the
// loaded libraries. gcc_eh does the rest.
int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data) {
int dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data) {
int rv = 0;
for (soinfo* si = solist; si != nullptr; si = si->next) {
dl_phdr_info dl_info;
@@ -950,17 +947,6 @@ static const ElfW(Sym)* dlsym_handle_lookup(soinfo* root, soinfo* skip_until,
// This is used by dlsym(3). It performs symbol lookup only within the
// specified soinfo object and its dependencies in breadth first order.
const ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name) {
// According to man dlopen(3) and posix docs in the case when si is handle
// of the main executable we need to search not only in the executable and its
// dependencies but also in all libraries loaded with RTLD_GLOBAL.
//
// Since RTLD_GLOBAL is always set for the main executable and all dt_needed shared
// libraries and they are loaded in breath-first (correct) order we can just execute
// dlsym(RTLD_DEFAULT, ...); instead of doing two stage lookup.
if (si == somain) {
return dlsym_linear_lookup(name, found, nullptr, RTLD_DEFAULT);
}
SymbolName symbol_name(name);
return dlsym_handle_lookup(si, nullptr, found, symbol_name);
}
@@ -988,10 +974,7 @@ const ElfW(Sym)* dlsym_linear_lookup(const char* name,
const ElfW(Sym)* s = nullptr;
for (soinfo* si = start; si != nullptr; si = si->next) {
// Do not skip RTLD_LOCAL libraries in dlsym(RTLD_DEFAULT, ...)
// if the library is opened by application with target api level <= 22
// See http://b/21565766
if ((si->get_rtld_flags() & RTLD_GLOBAL) == 0 && si->get_target_sdk_version() > 22) {
if ((si->get_rtld_flags() & RTLD_GLOBAL) == 0) {
continue;
}
@@ -1082,11 +1065,11 @@ static int open_library_in_zipfile(const char* const path,
off64_t* file_offset) {
TRACE("Trying zip file open from path '%s'", path);
// Treat an '!/' separator inside a path as the separator between the name
// Treat an '!' character inside a path as the separator between the name
// of the zip file on disk and the subdirectory to search within it.
// For example, if path is "foo.zip!/bar/bas/x.so", then we search for
// For example, if path is "foo.zip!bar/bas/x.so", then we search for
// "bar/bas/x.so" within "foo.zip".
const char* separator = strstr(path, "!/");
const char* separator = strchr(path, '!');
if (separator == nullptr) {
return -1;
}
@@ -1100,7 +1083,7 @@ static int open_library_in_zipfile(const char* const path,
buf[separator - path] = '\0';
const char* zip_path = buf;
const char* file_path = &buf[separator - path + 2];
const char* file_path = &buf[separator - path + 1];
int fd = TEMP_FAILURE_RETRY(open(zip_path, O_RDONLY | O_CLOEXEC));
if (fd == -1) {
return -1;
@@ -1217,26 +1200,11 @@ static int open_library(const char* name, off64_t* file_offset) {
return fd;
}
static const char* fix_dt_needed(const char* dt_needed, const char* sopath __unused) {
#if !defined(__LP64__)
// Work around incorrect DT_NEEDED entries for old apps: http://b/21364029
if (get_application_target_sdk_version() <= 22) {
const char* bname = basename(dt_needed);
if (bname != dt_needed) {
DL_WARN("'%s' library has invalid DT_NEEDED entry '%s'", sopath, dt_needed);
}
return bname;
}
#endif
return dt_needed;
}
template<typename F>
static void for_each_dt_needed(const soinfo* si, F action) {
for (ElfW(Dyn)* d = si->dynamic; d->d_tag != DT_NULL; ++d) {
if (d->d_tag == DT_NEEDED) {
action(fix_dt_needed(si->get_string(d->d_un.d_val), si->get_realpath()));
action(si->get_string(d->d_un.d_val));
}
}
}
@@ -1288,12 +1256,12 @@ static soinfo* load_library(int fd, off64_t file_offset,
std::string realpath = name;
if (!realpath_fd(fd, &realpath)) {
PRINT("warning: unable to get realpath for the library \"%s\". Will use given name.", name);
PRINT("cannot resolve realpath for the library \"%s\": %s", name, strerror(errno));
realpath = name;
}
// Read the ELF header and load the segments.
ElfReader elf_reader(realpath.c_str(), fd, file_offset, file_stat.st_size);
ElfReader elf_reader(realpath.c_str(), fd, file_offset);
if (!elf_reader.Load(extinfo)) {
return nullptr;
}
@@ -1343,63 +1311,30 @@ static soinfo* load_library(LoadTaskList& load_tasks,
return result;
}
// Returns true if library was found and false in 2 cases
// 1. The library was found but loaded under different target_sdk_version
// (*candidate != nullptr)
// 2. The library was not found by soname (*candidate is nullptr)
static bool find_loaded_library_by_soname(const char* name, soinfo** candidate) {
*candidate = nullptr;
static soinfo *find_loaded_library_by_soname(const char* name) {
// Ignore filename with path.
if (strchr(name, '/') != nullptr) {
return false;
return nullptr;
}
uint32_t target_sdk_version = get_application_target_sdk_version();
for (soinfo* si = solist; si != nullptr; si = si->next) {
const char* soname = si->get_soname();
if (soname != nullptr && (strcmp(name, soname) == 0)) {
// If the library was opened under different target sdk version
// skip this step and try to reopen it. The exceptions are
// "libdl.so" and global group. There is no point in skipping
// them because relocation process is going to use them
// in any case.
bool is_libdl = si == solist;
if (is_libdl || (si->get_dt_flags_1() & DF_1_GLOBAL) != 0 ||
!si->is_linked() || si->get_target_sdk_version() == target_sdk_version) {
*candidate = si;
return true;
} else if (*candidate == nullptr) {
// for the different sdk version - remember the first library.
*candidate = si;
}
return si;
}
}
return false;
return nullptr;
}
static soinfo* find_library_internal(LoadTaskList& load_tasks, const char* name,
int rtld_flags, const android_dlextinfo* extinfo) {
soinfo* candidate;
if (find_loaded_library_by_soname(name, &candidate)) {
return candidate;
}
soinfo* si = find_loaded_library_by_soname(name);
// Library might still be loaded, the accurate detection
// of this fact is done by load_library.
TRACE("[ '%s' find_loaded_library_by_soname returned false (*candidate=%s@%p). Trying harder...]",
name, candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
soinfo* si = load_library(load_tasks, name, rtld_flags, extinfo);
// In case we were unable to load the library but there
// is a candidate loaded under the same soname but different
// sdk level - return it anyways.
if (si == nullptr && candidate != nullptr) {
si = candidate;
if (si == nullptr) {
TRACE("[ '%s' has not been found by soname. Trying harder...]", name);
si = load_library(load_tasks, name, rtld_flags, extinfo);
}
return si;
@@ -1921,32 +1856,9 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
DL_ERR("unknown weak reloc type %d @ %p (%zu)", type, rel, idx);
return false;
}
} else { // We got a definition.
#if !defined(__LP64__)
// When relocating dso with text_relocation .text segment is
// not executable. We need to restore elf flags before resolving
// STT_GNU_IFUNC symbol.
bool protect_segments = has_text_relocations &&
lsi == this &&
ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC;
if (protect_segments) {
if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
DL_ERR("can't protect segments for \"%s\": %s",
get_realpath(), strerror(errno));
return false;
}
}
#endif
} else {
// We got a definition.
sym_addr = lsi->resolve_symbol_address(s);
#if !defined(__LP64__)
if (protect_segments) {
if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
DL_ERR("can't unprotect loadable segments for \"%s\": %s",
get_realpath(), strerror(errno));
return false;
}
}
#endif
}
count_relocation(kRelocSymbol);
}
@@ -1983,32 +1895,7 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
TRACE_TYPE(RELO, "RELO IRELATIVE %16p <- %16p\n",
reinterpret_cast<void*>(reloc),
reinterpret_cast<void*>(load_bias + addend));
{
#if !defined(__LP64__)
// When relocating dso with text_relocation .text segment is
// not executable. We need to restore elf flags for this
// particular call.
if (has_text_relocations) {
if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
DL_ERR("can't protect segments for \"%s\": %s",
get_realpath(), strerror(errno));
return false;
}
}
#endif
ElfW(Addr) ifunc_addr = call_ifunc_resolver(load_bias + addend);
#if !defined(__LP64__)
// Unprotect it afterwards...
if (has_text_relocations) {
if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
DL_ERR("can't unprotect loadable segments for \"%s\": %s",
get_realpath(), strerror(errno));
return false;
}
}
#endif
*reinterpret_cast<ElfW(Addr)*>(reloc) = ifunc_addr;
}
*reinterpret_cast<ElfW(Addr)*>(reloc) = call_ifunc_resolver(load_bias + addend);
break;
#if defined(__aarch64__)
@@ -2476,15 +2363,64 @@ soinfo* soinfo::get_local_group_root() const {
return local_group_root_;
}
// This function returns api-level at the time of
// dlopen/load. Note that libraries opened by system
// will always have 'current' api level.
uint32_t soinfo::get_target_sdk_version() const {
if (!has_min_version(2)) {
return __ANDROID_API__;
/* Force any of the closed stdin, stdout and stderr to be associated with
/dev/null. */
static int nullify_closed_stdio() {
int dev_null, i, status;
int return_value = 0;
dev_null = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
if (dev_null < 0) {
DL_ERR("cannot open /dev/null: %s", strerror(errno));
return -1;
}
TRACE("[ Opened /dev/null file-descriptor=%d]", dev_null);
/* If any of the stdio file descriptors is valid and not associated
with /dev/null, dup /dev/null to it. */
for (i = 0; i < 3; i++) {
/* If it is /dev/null already, we are done. */
if (i == dev_null) {
continue;
}
TRACE("[ Nullifying stdio file descriptor %d]", i);
status = TEMP_FAILURE_RETRY(fcntl(i, F_GETFL));
/* If file is opened, we are good. */
if (status != -1) {
continue;
}
/* The only error we allow is that the file descriptor does not
exist, in which case we dup /dev/null to it. */
if (errno != EBADF) {
DL_ERR("fcntl failed: %s", strerror(errno));
return_value = -1;
continue;
}
/* Try dupping /dev/null to this stdio file descriptor and
repeat if there is a signal. Note that any errors in closing
the stdio descriptor are lost. */
status = TEMP_FAILURE_RETRY(dup2(dev_null, i));
if (status < 0) {
DL_ERR("dup2 failed: %s", strerror(errno));
return_value = -1;
continue;
}
}
return local_group_root_->target_sdk_version_;
/* If /dev/null is not one of the stdio file descriptors, close it. */
if (dev_null > 2) {
TRACE("[ Closing /dev/null file-descriptor=%d]", dev_null);
if (close(dev_null) == -1) {
DL_ERR("close failed: %s", strerror(errno));
return_value = -1;
}
}
return return_value;
}
bool soinfo::prelink_image() {
@@ -2794,7 +2730,7 @@ bool soinfo::prelink_image() {
set_dt_flags_1(d->d_un.d_val);
if ((d->d_un.d_val & ~SUPPORTED_DT_FLAGS_1) != 0) {
DL_WARN("%s: unsupported flags DT_FLAGS_1=%p", get_realpath(), reinterpret_cast<void*>(d->d_un.d_val));
DL_WARN("Unsupported flags DT_FLAGS_1=%p", reinterpret_cast<void*>(d->d_un.d_val));
}
break;
#if defined(__mips__)
@@ -2864,6 +2800,17 @@ bool soinfo::prelink_image() {
}
}
// second pass - parse entries relying on strtab
for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
if (d->d_tag == DT_SONAME) {
soname_ = get_string(d->d_un.d_val);
#if defined(__work_around_b_19059885__)
strlcpy(old_name_, soname_, sizeof(old_name_));
#endif
break;
}
}
DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p",
reinterpret_cast<void*>(base), strtab_, symtab_);
@@ -2885,30 +2832,6 @@ bool soinfo::prelink_image() {
DL_ERR("empty/missing DT_SYMTAB in \"%s\"", get_realpath());
return false;
}
// second pass - parse entries relying on strtab
for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
if (d->d_tag == DT_SONAME) {
soname_ = get_string(d->d_un.d_val);
#if defined(__work_around_b_19059885__)
strlcpy(old_name_, soname_, sizeof(old_name_));
#endif
break;
}
}
// Before M release linker was using basename in place of soname.
// In the case when dt_soname is absent some apps stop working
// because they can't find dt_needed library by soname.
// This workaround should keep them working. (applies only
// for apps targeting sdk version <=22). Make an exception for
// the main executable and linker; they do not need to have dt_soname
if (soname_ == nullptr && this != somain && (flags_ & FLAG_LINKER) == 0 &&
get_application_target_sdk_version() <= 22) {
soname_ = basename(realpath_.c_str());
DL_WARN("%s: is missing DT_SONAME will use basename as a replacement: \"%s\"",
get_realpath(), soname_);
}
return true;
}
@@ -2920,10 +2843,6 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
local_group_root_ = this;
}
if ((flags_ & FLAG_LINKER) == 0 && local_group_root_ == this) {
target_sdk_version_ = get_application_target_sdk_version();
}
VersionTracker version_tracker;
if (!version_tracker.init(this)) {
@@ -2932,13 +2851,6 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
#if !defined(__LP64__)
if (has_text_relocations) {
// Fail if app is targeting sdk version > 22
// TODO (dimitry): remove != __ANDROID_API__ check once http://b/20020312 is fixed
if (get_application_target_sdk_version() != __ANDROID_API__
&& get_application_target_sdk_version() > 22) {
DL_ERR("%s: has text relocations", get_realpath());
return false;
}
// Make segments writable to allow text relocations to work properly. We will later call
// phdr_table_protect_segments() after all of them are applied and all constructors are run.
DL_WARN("%s has text relocations. This is wasting memory and prevents "
@@ -3108,7 +3020,7 @@ static soinfo* linker_soinfo_for_gdb = nullptr;
static void init_linker_info_for_gdb(ElfW(Addr) linker_base) {
linker_soinfo_for_gdb = new (linker_soinfo_for_gdb_buf) soinfo(LINKER_PATH, nullptr, 0, 0);
linker_soinfo_for_gdb->load_bias = linker_base;
linker_soinfo_for_gdb->base = linker_base;
/*
* Set the dynamic field in the link map otherwise gdb will complain with
@@ -3136,29 +3048,41 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
gettimeofday(&t0, 0);
#endif
// Sanitize the environment.
__libc_init_AT_SECURE(args);
// Initialize environment functions, and get to the ELF aux vectors table.
linker_env_init(args);
// Initialize system properties
__system_properties_init(); // may use 'environ'
// If this is a setuid/setgid program, close the security hole described in
// ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-02:23.stdio.asc
if (get_AT_SECURE()) {
nullify_closed_stdio();
}
debuggerd_init();
// Get a few environment variables.
const char* LD_DEBUG = getenv("LD_DEBUG");
const char* LD_DEBUG = linker_env_get("LD_DEBUG");
if (LD_DEBUG != nullptr) {
g_ld_debug_verbosity = atoi(LD_DEBUG);
}
// These should have been sanitized by __libc_init_AT_SECURE, but the test
// Normally, these are cleaned by linker_env_init, but the test
// doesn't cost us anything.
const char* ldpath_env = nullptr;
const char* ldpreload_env = nullptr;
if (!getauxval(AT_SECURE)) {
ldpath_env = getenv("LD_LIBRARY_PATH");
ldpreload_env = getenv("LD_PRELOAD");
if (!get_AT_SECURE()) {
ldpath_env = linker_env_get("LD_LIBRARY_PATH");
ldpreload_env = linker_env_get("LD_PRELOAD");
}
#if !defined(__LP64__)
if (personality(PER_LINUX32) == -1) {
__libc_fatal("error setting PER_LINUX32 personality: %s", strerror(errno));
}
#endif
INFO("[ android linker & debugger ]");
soinfo* si = soinfo_alloc(args.argv[0], nullptr, 0, RTLD_GLOBAL);

View File

@@ -334,8 +334,6 @@ struct soinfo {
bool find_verdef_version_index(const version_info* vi, ElfW(Versym)* versym) const;
uint32_t get_target_sdk_version() const;
private:
bool elf_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;
ElfW(Sym)* elf_addr_lookup(const void* addr);
@@ -395,8 +393,6 @@ struct soinfo {
ElfW(Addr) verneed_ptr_;
size_t verneed_cnt_;
uint32_t target_sdk_version_;
friend soinfo* get_libdl_info();
};
@@ -421,8 +417,6 @@ void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path);
soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo);
void do_dlclose(soinfo* si);
int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data);
const ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* caller, void* handle);
soinfo* find_containing_library(const void* addr);

191
linker/linker_environ.cpp Normal file
View File

@@ -0,0 +1,191 @@
/*
* Copyright (C) 2010 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "linker_environ.h"
#include <linux/auxvec.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "private/KernelArgumentBlock.h"
static bool _AT_SECURE_value = true;
bool get_AT_SECURE() {
return _AT_SECURE_value;
}
static void __init_AT_SECURE(KernelArgumentBlock& args) {
// Check auxv for AT_SECURE first to see if program is setuid, setgid,
// has file caps, or caused a SELinux/AppArmor domain transition.
bool kernel_supplied_AT_SECURE;
_AT_SECURE_value = args.getauxval(AT_SECURE, &kernel_supplied_AT_SECURE);
// We don't support ancient kernels.
if (!kernel_supplied_AT_SECURE) {
const char* msg = "FATAL: kernel did not supply AT_SECURE\n";
write(2, msg, strlen(msg));
exit(EXIT_FAILURE);
}
}
// Check if the environment variable definition at 'envstr'
// starts with '<name>=', and if so return the address of the
// first character after the equal sign. Otherwise return null.
static const char* env_match(const char* envstr, const char* name) {
size_t i = 0;
while (envstr[i] == name[i] && name[i] != '\0') {
++i;
}
if (name[i] == '\0' && envstr[i] == '=') {
return envstr + i + 1;
}
return nullptr;
}
static bool __is_valid_environment_variable(const char* name) {
// According to its sources, the kernel uses 32*PAGE_SIZE by default
// as the maximum size for an env. variable definition.
const int MAX_ENV_LEN = 32*4096;
if (name == nullptr) {
return false;
}
// Parse the string, looking for the first '=' there, and its size.
int pos = 0;
int first_equal_pos = -1;
while (pos < MAX_ENV_LEN) {
if (name[pos] == '\0') {
break;
}
if (name[pos] == '=' && first_equal_pos < 0) {
first_equal_pos = pos;
}
pos++;
}
// Check that it's smaller than MAX_ENV_LEN (to detect non-zero terminated strings).
if (pos >= MAX_ENV_LEN) {
return false;
}
// Check that it contains at least one equal sign that is not the first character
if (first_equal_pos < 1) {
return false;
}
return true;
}
static bool __is_unsafe_environment_variable(const char* name) {
// None of these should be allowed in setuid programs.
static const char* const UNSAFE_VARIABLE_NAMES[] = {
"GCONV_PATH",
"GETCONF_DIR",
"HOSTALIASES",
"JE_MALLOC_CONF",
"LD_AOUT_LIBRARY_PATH",
"LD_AOUT_PRELOAD",
"LD_AUDIT",
"LD_DEBUG",
"LD_DEBUG_OUTPUT",
"LD_DYNAMIC_WEAK",
"LD_LIBRARY_PATH",
"LD_ORIGIN_PATH",
"LD_PRELOAD",
"LD_PROFILE",
"LD_SHOW_AUXV",
"LD_USE_LOAD_BIAS",
"LOCALDOMAIN",
"LOCPATH",
"MALLOC_CHECK_",
"MALLOC_CONF",
"MALLOC_TRACE",
"NIS_PATH",
"NLSPATH",
"RESOLV_HOST_CONF",
"RES_OPTIONS",
"TMPDIR",
"TZDIR",
nullptr
};
for (size_t i = 0; UNSAFE_VARIABLE_NAMES[i] != nullptr; ++i) {
if (env_match(name, UNSAFE_VARIABLE_NAMES[i]) != nullptr) {
return true;
}
}
return false;
}
static void __sanitize_environment_variables() {
char** src = environ;
char** dst = environ;
for (; src[0] != nullptr; ++src) {
if (!__is_valid_environment_variable(src[0])) {
continue;
}
// Remove various unsafe environment variables if we're loading a setuid program.
if (get_AT_SECURE() && __is_unsafe_environment_variable(src[0])) {
continue;
}
dst[0] = src[0];
++dst;
}
dst[0] = nullptr;
}
void linker_env_init(KernelArgumentBlock& args) {
// Store environment pointer - can't be null.
environ = args.envp;
__init_AT_SECURE(args);
__sanitize_environment_variables();
}
const char* linker_env_get(const char* name) {
if (name == nullptr || name[0] == '\0') {
return nullptr;
}
for (char** p = environ; p[0] != nullptr; ++p) {
const char* val = env_match(p[0], name);
if (val != nullptr) {
if (val[0] == '\0') {
return nullptr; // Return null for empty strings.
}
return val;
}
}
return nullptr;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2010 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,34 +26,19 @@
* SUCH DAMAGE.
*/
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/xattr.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#ifndef LINKER_ENVIRON_H
#define LINKER_ENVIRON_H
extern "C" ssize_t ___fgetxattr(int, const char*, void*, size_t);
class KernelArgumentBlock;
ssize_t fgetxattr(int fd, const char *name, void *value, size_t size) {
int saved_errno = errno;
ssize_t result = ___fgetxattr(fd, name, value, size);
// Call this function before any of the other functions in this header file.
extern void linker_env_init(KernelArgumentBlock& args);
if ((result != -1) || (errno != EBADF)) {
return result;
}
// Returns the value of environment variable 'name' if defined and not
// empty, or null otherwise.
extern const char* linker_env_get(const char* name);
// fd could be an O_PATH file descriptor, and the kernel
// may not directly support fgetxattr() on such a file descriptor.
// Use /proc/self/fd instead to emulate this support.
int fd_flag = fcntl(fd, F_GETFL);
if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
errno = EBADF;
return -1;
}
// Returns the value of this program's AT_SECURE variable.
extern bool get_AT_SECURE();
char buf[40];
snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
errno = saved_errno;
return getxattr(buf, name, value, size);
}
#endif // LINKER_ENVIRON_H

View File

@@ -133,8 +133,8 @@ static int GetTargetElfMachine() {
MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \
MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE))
ElfReader::ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size)
: name_(name), fd_(fd), file_offset_(file_offset), file_size_(file_size),
ElfReader::ElfReader(const char* name, int fd, off64_t file_offset)
: name_(name), fd_(fd), file_offset_(file_offset),
phdr_num_(0), phdr_mmap_(nullptr), phdr_table_(nullptr), phdr_size_(0),
load_start_(nullptr), load_size_(0), load_bias_(0),
loaded_phdr_(nullptr) {
@@ -316,8 +316,6 @@ bool ElfReader::ReserveAddressSpace(const android_dlextinfo* extinfo) {
void* start;
size_t reserved_size = 0;
bool reserved_hint = true;
// Assume position independent executable by default.
uint8_t* mmap_hint = nullptr;
if (extinfo != nullptr) {
if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) {
@@ -326,10 +324,6 @@ bool ElfReader::ReserveAddressSpace(const android_dlextinfo* extinfo) {
} else if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_HINT) {
reserved_size = extinfo->reserved_size;
}
if ((extinfo->flags & ANDROID_DLEXT_FORCE_FIXED_VADDR) != 0) {
mmap_hint = addr;
}
}
if (load_size_ > reserved_size) {
@@ -339,7 +333,7 @@ bool ElfReader::ReserveAddressSpace(const android_dlextinfo* extinfo) {
return false;
}
int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
start = mmap(mmap_hint, load_size_, PROT_NONE, mmap_flags, -1, 0);
start = mmap(nullptr, load_size_, PROT_NONE, mmap_flags, -1, 0);
if (start == MAP_FAILED) {
DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_);
return false;
@@ -377,20 +371,6 @@ bool ElfReader::LoadSegments() {
ElfW(Addr) file_page_start = PAGE_START(file_start);
ElfW(Addr) file_length = file_end - file_page_start;
if (file_size_ <= 0) {
DL_ERR("\"%s\" invalid file size: %" PRId64, name_, file_size_);
return false;
}
if (file_end >= static_cast<size_t>(file_size_)) {
DL_ERR("invalid ELF file \"%s\" load segment[%zd]:"
" p_offset (%p) + p_filesz (%p) ( = %p) past end of file (0x%" PRIx64 ")",
name_, i, reinterpret_cast<void*>(phdr->p_offset),
reinterpret_cast<void*>(phdr->p_filesz),
reinterpret_cast<void*>(file_end), file_size_);
return false;
}
if (file_length != 0) {
void* seg_addr = mmap64(reinterpret_cast<void*>(seg_page_start),
file_length,

View File

@@ -39,7 +39,7 @@
class ElfReader {
public:
ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size);
ElfReader(const char* name, int fd, off64_t file_offset);
~ElfReader();
bool Load(const android_dlextinfo* extinfo);
@@ -62,7 +62,6 @@ class ElfReader {
const char* name_;
int fd_;
off64_t file_offset_;
off64_t file_size_;
ElfW(Ehdr) header_;
size_t phdr_num_;

View File

@@ -15,16 +15,11 @@
*/
#include "linker.h"
#include <android/api-level.h>
#include <atomic>
static std::atomic<uint32_t> g_target_sdk_version(__ANDROID_API__);
static std::atomic<uint32_t> g_target_sdk_version;
void set_application_target_sdk_version(uint32_t target) {
// translate current sdk_version to platform sdk_version
if (target == 0) {
target = __ANDROID_API__;
}
g_target_sdk_version = target;
}

View File

@@ -49,6 +49,9 @@ endif
test_cppflags = \
-std=gnu++11 \
libBionicStandardTests_src_files_target := \
libdl_test.cpp \
libBionicStandardTests_src_files := \
arpa_inet_test.cpp \
buffer_tests.cpp \
@@ -93,7 +96,6 @@ libBionicStandardTests_src_files := \
sys_epoll_test.cpp \
sys_mman_test.cpp \
sys_personality_test.cpp \
sys_procfs_test.cpp \
sys_resource_test.cpp \
sys_select_test.cpp \
sys_sendfile_test.cpp \
@@ -104,9 +106,7 @@ libBionicStandardTests_src_files := \
sys_sysinfo_test.cpp \
sys_time_test.cpp \
sys_types_test.cpp \
sys_uio_test.cpp \
sys_vfs_test.cpp \
sys_xattr_test.cpp \
system_properties_test.cpp \
time_test.cpp \
uchar_test.cpp \
@@ -241,12 +241,7 @@ libBionicCtsGtestMain_src_files := gtest_main.cpp
libBionicCtsGtestMain_cflags := $(test_cflags)
libBionicCtsGtestMain_cppflags := $(test_cppflags) -DUSING_GTEST_OUTPUT_FORMAT \
# Temporarily fix the job count to 1 for CTS since on some devices the
# number of online cores is incorrectly read as the total number of cores
# in the system. When b/24376925 is fixed, this should be removed.
libBionicCtsGtestMain_cppflags += -DJOB_COUNT_FIXED=1
libBionicCtsGtestMain_cppflags := $(test_cppflags) -DUSING_GTEST_OUTPUT_FORMAT
module := libBionicCtsGtestMain
module_tag := optional
@@ -277,7 +272,6 @@ bionic-unit-tests_src_files := \
dlext_test.cpp \
__cxa_thread_atexit_test.cpp \
dlfcn_test.cpp \
libdl_test.cpp \
pthread_dlfcn_test.cpp \
bionic-unit-tests_cflags := $(test_cflags)
@@ -407,7 +401,7 @@ LOCAL_ADDITIONAL_DEPENDENCIES := \
LOCAL_CXX = $(LOCAL_PATH)/file-check-cxx \
$(HOST_OUT_EXECUTABLES)/FileCheck \
$($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_CXX) \
$($(LOCAL_2ND_ARCH_VAR_PREFIX)CXX_BARE) \
GCC \
LOCAL_CLANG := false

View File

@@ -214,7 +214,7 @@ TEST(dlext, android_dlopen_ext_force_load_soname_exception) {
TEST(dlfcn, dlopen_from_zip_absolute_path) {
const std::string lib_path = std::string(getenv("ANDROID_DATA")) + LIBZIPPATH;
void* handle = dlopen((lib_path + "!/libdir/libdlext_test_fd.so").c_str(), RTLD_NOW);
void* handle = dlopen((lib_path + "!libdir/libdlext_test_fd.so").c_str(), RTLD_NOW);
ASSERT_TRUE(handle != nullptr) << dlerror();
int (*fn)(void);
@@ -226,7 +226,7 @@ TEST(dlfcn, dlopen_from_zip_absolute_path) {
}
TEST(dlfcn, dlopen_from_zip_ld_library_path) {
const std::string lib_path = std::string(getenv("ANDROID_DATA")) + LIBZIPPATH + "!/libdir";
const std::string lib_path = std::string(getenv("ANDROID_DATA")) + LIBZIPPATH + "!libdir";
typedef void (*fn_t)(const char*);
fn_t android_update_LD_LIBRARY_PATH =

View File

@@ -145,28 +145,13 @@ TEST(dlfcn, dlsym_from_sofile_with_preload) {
dlclose(preload);
}
TEST(dlfcn, dlsym_handle_global_sym) {
// check that we do not look into global group
// when looking up symbol by handle
void* handle = dlopen("libtest_empty.so", RTLD_NOW);
dlopen("libtest_with_dependency.so", RTLD_NOW | RTLD_GLOBAL);
void* sym = dlsym(handle, "getRandomNumber");
ASSERT_TRUE(sym == nullptr);
ASSERT_SUBSTR("undefined symbol: getRandomNumber", dlerror());
sym = dlsym(handle, "DlSymTestFunction");
ASSERT_TRUE(sym == nullptr);
ASSERT_SUBSTR("undefined symbol: DlSymTestFunction", dlerror());
dlclose(handle);
}
TEST(dlfcn, dlsym_with_dependencies) {
void* handle = dlopen("libtest_with_dependency.so", RTLD_NOW);
ASSERT_TRUE(handle != nullptr);
ASSERT_TRUE(handle != NULL);
dlerror();
// This symbol is in DT_NEEDED library.
void* sym = dlsym(handle, "getRandomNumber");
ASSERT_TRUE(sym != nullptr) << dlerror();
ASSERT_TRUE(sym != NULL);
int (*fn)(void);
fn = reinterpret_cast<int (*)(void)>(sym);
EXPECT_EQ(4, fn());
@@ -598,15 +583,6 @@ TEST(dlfcn, dlopen_check_rtld_global) {
// RTLD_GLOBAL implies RTLD_NODELETE, let's check that
void* sym_after_dlclose = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
ASSERT_EQ(sym, sym_after_dlclose);
// Check if dlsym() for main program's handle searches RTLD_GLOBAL
// shared libraries after symbol was not found in the main executable
// and dependent libraries.
void* handle_for_main_executable = dlopen(nullptr, RTLD_NOW);
sym = dlsym(handle_for_main_executable, "dlopen_testlib_simple_func");
ASSERT_TRUE(sym != nullptr) << dlerror();
dlclose(handle_for_main_executable);
}
// libtest_with_dependency_loop.so -> libtest_with_dependency_loop_a.so ->

View File

@@ -59,7 +59,7 @@ using testing::internal::COLOR_GREEN;
using testing::internal::COLOR_YELLOW;
using testing::internal::ColoredPrintf;
constexpr int DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS = 90000;
constexpr int DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS = 60000;
constexpr int DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS = 2000;
// The time each test can run before killed for the reason of timeout.
@@ -839,12 +839,8 @@ static bool RunTestInSeparateProc(int argc, char** argv, std::vector<TestCase>&
return all_tests_passed;
}
static size_t GetDefaultJobCount() {
#if defined(JOB_COUNT_FIXED)
return JOB_COUNT_FIXED;
#else
static size_t GetProcessorCount() {
return static_cast<size_t>(sysconf(_SC_NPROCESSORS_ONLN));
#endif
}
static void AddPathSeparatorInTestProgramPath(std::vector<char*>& args) {
@@ -954,7 +950,7 @@ static bool PickOptions(std::vector<char*>& args, IsolationTestOptions& options)
}
// Init default isolation test options.
options.job_count = GetDefaultJobCount();
options.job_count = GetProcessorCount();
options.test_deadline_ms = DEFAULT_GLOBAL_TEST_RUN_DEADLINE_MS;
options.test_warnline_ms = DEFAULT_GLOBAL_TEST_RUN_WARNLINE_MS;
options.gtest_color = testing::GTEST_FLAG(color);

View File

@@ -16,14 +16,12 @@
#include <gtest/gtest.h>
#include <android/api-level.h>
extern "C" uint32_t android_get_application_target_sdk_version();
extern "C" void android_set_application_target_sdk_version(uint32_t target);
TEST(libdl, application_sdk_versions_smoke) {
// Check initial values
ASSERT_EQ(static_cast<uint32_t>(__ANDROID_API__), android_get_application_target_sdk_version());
ASSERT_EQ(0U, android_get_application_target_sdk_version());
android_set_application_target_sdk_version(20U);
ASSERT_EQ(20U, android_get_application_target_sdk_version());

View File

@@ -404,14 +404,6 @@ libtest_dlsym_from_this_grandchild_src_files := dlsym_from_this_symbol2.cpp
module := libtest_dlsym_from_this_grandchild
include $(LOCAL_PATH)/Android.build.testlib.mk
# -----------------------------------------------------------------------------
# Empty library
# -----------------------------------------------------------------------------
libtest_empty_src_files := empty.cpp
module := libtest_empty
include $(LOCAL_PATH)/Android.build.testlib.mk
# -----------------------------------------------------------------------------
# Library with weak undefined function
# -----------------------------------------------------------------------------

55
tests/pthread_test.cpp Executable file → Normal file
View File

@@ -1154,6 +1154,7 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
// The two methods of asking for the stack size should agree.
EXPECT_EQ(stack_size, stack_size2);
#if defined(__BIONIC__)
// What does /proc/self/maps' [stack] line say?
void* maps_stack_hi = NULL;
FILE* fp = fopen("/proc/self/maps", "r");
@@ -1170,15 +1171,18 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
}
fclose(fp);
// The high address of the /proc/self/maps [stack] region should equal stack_base + stack_size.
// Remember that the stack grows down (and is mapped in on demand), so the low address of the
// region isn't very interesting.
EXPECT_EQ(maps_stack_hi, reinterpret_cast<uint8_t*>(stack_base) + stack_size);
// The stack size should correspond to RLIMIT_STACK.
rlimit rl;
ASSERT_EQ(0, getrlimit(RLIMIT_STACK, &rl));
uint64_t original_rlim_cur = rl.rlim_cur;
#if defined(__BIONIC__)
if (rl.rlim_cur == RLIM_INFINITY) {
rl.rlim_cur = 8 * 1024 * 1024; // Bionic reports unlimited stacks as 8MiB.
}
#endif
EXPECT_EQ(rl.rlim_cur, stack_size);
auto guard = make_scope_guard([&rl, original_rlim_cur]() {
@@ -1186,11 +1190,6 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
});
// The high address of the /proc/self/maps [stack] region should equal stack_base + stack_size.
// Remember that the stack grows down (and is mapped in on demand), so the low address of the
// region isn't very interesting.
EXPECT_EQ(maps_stack_hi, reinterpret_cast<uint8_t*>(stack_base) + stack_size);
//
// What if RLIMIT_STACK is smaller than the stack's current extent?
//
@@ -1218,6 +1217,7 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
EXPECT_EQ(stack_size, stack_size2);
ASSERT_EQ(6666U, stack_size);
#endif
}
static void pthread_attr_getstack_18908062_helper(void*) {
@@ -1244,11 +1244,8 @@ TEST(pthread, pthread_attr_getstack_18908062) {
}
#if defined(__BIONIC__)
static pthread_mutex_t gettid_mutex;
static void* pthread_gettid_np_helper(void* arg) {
pthread_mutex_lock(&gettid_mutex);
*reinterpret_cast<pid_t*>(arg) = gettid();
pthread_mutex_unlock(&gettid_mutex);
return NULL;
}
#endif
@@ -1259,15 +1256,11 @@ TEST(pthread, pthread_gettid_np) {
pid_t t_gettid_result;
pthread_t t;
pthread_mutex_init(&gettid_mutex, NULL);
pthread_mutex_lock(&gettid_mutex);
pthread_create(&t, NULL, pthread_gettid_np_helper, &t_gettid_result);
pid_t t_pthread_gettid_np_result = pthread_gettid_np(t);
pthread_mutex_unlock(&gettid_mutex);
pthread_join(t, NULL);
pthread_mutex_destroy(&gettid_mutex);
ASSERT_EQ(t_gettid_result, t_pthread_gettid_np_result);
#else
@@ -1544,37 +1537,3 @@ TEST(pthread, pthread_types_allow_four_bytes_alignment) {
GTEST_LOG_(INFO) << "This test tests bionic implementation details.";
#endif
}
TEST(pthread, pthread_mutex_lock_null_32) {
#if defined(__BIONIC__) && !defined(__LP64__)
ASSERT_EQ(EINVAL, pthread_mutex_lock(NULL));
#else
GTEST_LOG_(INFO) << "This test tests bionic implementation details on 32 bit devices.";
#endif
}
TEST(pthread, pthread_mutex_unlock_null_32) {
#if defined(__BIONIC__) && !defined(__LP64__)
ASSERT_EQ(EINVAL, pthread_mutex_unlock(NULL));
#else
GTEST_LOG_(INFO) << "This test tests bionic implementation details on 32 bit devices.";
#endif
}
TEST_F(pthread_DeathTest, pthread_mutex_lock_null_64) {
#if defined(__BIONIC__) && defined(__LP64__)
pthread_mutex_t* null_value = nullptr;
ASSERT_EXIT(pthread_mutex_lock(null_value), testing::KilledBySignal(SIGSEGV), "");
#else
GTEST_LOG_(INFO) << "This test tests bionic implementation details on 64 bit devices.";
#endif
}
TEST_F(pthread_DeathTest, pthread_mutex_unlock_null_64) {
#if defined(__BIONIC__) && defined(__LP64__)
pthread_mutex_t* null_value = nullptr;
ASSERT_EXIT(pthread_mutex_unlock(null_value), testing::KilledBySignal(SIGSEGV), "");
#else
GTEST_LOG_(INFO) << "This test tests bionic implementation details on 64 bit devices.";
#endif
}

Some files were not shown because too many files have changed in this diff Show More