Compare commits

..

109 Commits

Author SHA1 Message Date
The Android Automerger
63d2f6db2e merge in lmp-mr1-release history after reset to lmp-mr1-dev 2015-02-04 06:08:53 -08:00
The Android Automerger
f0b38a3fc9 merge in lmp-mr1-release history after reset to lmp-mr1-dev 2015-01-08 09:31:57 -08:00
The Android Automerger
ecb7dcc084 merge in lmp-mr1-release history after reset to lmp-mr1-dev 2014-12-08 06:09:01 -08:00
The Android Automerger
f6f04b82e2 merge in lmp-mr1-release history after reset to lmp-mr1-dev 2014-12-03 06:08:43 -08:00
The Android Automerger
25726c8ce4 merge in lmp-mr1-release history after reset to lmp-mr1-dev 2014-12-02 06:08:56 -08:00
The Android Automerger
fffca9eb3d merge in lmp-mr1-release history after reset to lmp-mr1-dev 2014-11-24 06:09:01 -08:00
The Android Automerger
d602328201 merge in lmp-mr1-release history after reset to lmp-mr1-dev 2014-11-18 06:09:23 -08:00
The Android Automerger
fa06d6dba7 merge in lmp-mr1-release history after reset to lmp-mr1-dev 2014-11-17 06:09:15 -08:00
The Android Automerger
5831077f76 merge in lmp-mr1-release history after reset to lmp-mr1-dev 2014-11-13 06:10:24 -08:00
The Android Automerger
5553ed1e85 merge in lmp-mr1-release history after reset to 9d3382d97a2cdc8c8f78c7825ece16f09292fc36 2014-11-08 06:09:36 -08:00
The Android Automerger
4107b7d092 merge in lmp-mr1-release history after reset to 9d3382d97a2cdc8c8f78c7825ece16f09292fc36 2014-11-06 06:09:56 -08:00
The Android Automerger
b8e430701e merge in lmp-mr1-release history after reset to 9d3382d97a2cdc8c8f78c7825ece16f09292fc36 2014-11-05 06:09:40 -08:00
Dmitriy Ivanov
e4ae96ffd3 Revert "Fix dlsym() to take into account RTLD_GLOBAL/LOCAL"
This reverts commit c85e82dde5c4b2accc50a9e17740b9005dfbae6a.

Bug: 18222321
Bug: 18211780
Change-Id: I32f4048bd5ea85dc8a3dfccce8cf141b241ab692
2014-11-04 14:07:46 -08:00
Dmitriy Ivanov
d84897d4a3 Revert "Add RTLD_NODELETE flag support"
This reverts commit c87f65d2cd0690d81665f8b241c1d763f72b6f80.

Bug: 18222321
Bug: 18211780
Change-Id: I00252e26a28a41ab9f1e2dd3b32f0f80d86297f1
2014-11-04 14:07:46 -08:00
Dmitriy Ivanov
189ac9f142 Revert "Fix relocation to look for symbols in local group"
This reverts commit fd2747bb585fc51b5ad56db09c0e9b66c7091a92.

Bug: 18222321
Bug: 18211780
Change-Id: I2d4ebab1e73b7277161af76b99f8249825b22d65
2014-11-04 14:07:46 -08:00
Dmitriy Ivanov
8bf7353b79 Revert "Remove unnecessary lookups during relocations"
This reverts commit 6442dbd3bcadbd5e522465743a8d8cf56338ae1c.

Bug: 18222321
Bug: 18211780
Change-Id: I87b18a32238a1f75afe56149221b6691f50d9f56
2014-11-04 14:07:46 -08:00
Dmitriy Ivanov
8b952f5552 Revert "Fix mips build"
This reverts commit bf3d5ef5fd240d4c5fbde1b32f9084dbc720840b.

Bug: 18222321
Bug: 18211780
Change-Id: I902ed888197b358c77303f1acb6d5ffd7ae6dcd3
2014-11-04 14:07:46 -08:00
Dmitriy Ivanov
86fdf8f09b Revert "Fix symbol lookup order during relocation"
This reverts commit 976402cca13a1f4f3aa988fd301575e134ef5f2c.

Bug: 18222321
Bug: 18211780
Change-Id: Iafdd3d843db7b1cf288be9a0232022816622c944
2014-11-04 14:07:46 -08:00
Dmitriy Ivanov
b9f21a08f3 Revert "Fix arm64 and arm builds."
This reverts commit 445111a1c977e94a4233efd54f3690defa4a7582.

Bug: 18222321
Bug: 18211780
Change-Id: I4fa9e1b63ec9b528f8bfed73c2ec15046c43a2fe
2014-11-04 14:07:46 -08:00
The Android Automerger
0c7105c69f merge in lmp-mr1-release history after reset to d18f4b25785761c022906b93b2123b3be90182e8 2014-11-04 06:09:42 -08:00
The Android Automerger
99e148e30c merge in lmp-mr1-release history after reset to 445111a1c977e94a4233efd54f3690defa4a7582 2014-11-03 06:09:01 -08:00
The Android Automerger
b0daba3da1 merge in lmp-mr1-release history after reset to 445111a1c977e94a4233efd54f3690defa4a7582 2014-11-02 06:08:55 -08:00
The Android Automerger
13baf92d93 merge in lmp-mr1-release history after reset to 653263a96459c5c1811623bd84201c324a870280 2014-11-01 06:09:02 -07:00
The Android Automerger
09fa97fd17 merge in lmp-mr1-release history after reset to b0693ec58247c36a7427267783cb756cc055aed8 2014-10-30 06:08:57 -07:00
The Android Automerger
609f5cb21d merge in lmp-mr1-release history after reset to 0cc59dd303205de7110e298e9b90b1c3b98f4711 2014-10-29 06:08:51 -07:00
The Android Automerger
05c3adbabf merge in lmp-mr1-release history after reset to aa6cd5819c8ebd254d995388798a4b51af7ca933 2014-10-28 06:10:08 -07:00
The Android Automerger
b50945d935 merge in lmp-mr1-release history after reset to aa6cd5819c8ebd254d995388798a4b51af7ca933 2014-10-27 06:08:44 -07:00
The Android Automerger
fa29966094 merge in lmp-mr1-release history after reset to aa6cd5819c8ebd254d995388798a4b51af7ca933 2014-10-26 06:08:41 -07:00
The Android Automerger
5c9ba49803 merge in lmp-mr1-release history after reset to aa6cd5819c8ebd254d995388798a4b51af7ca933 2014-10-25 06:08:59 -07:00
The Android Automerger
0e5f7b9b3c merge in lmp-mr1-release history after reset to 8fab8119dd176a280b62e9e8f2b4f08c0d76f36d 2014-10-23 06:09:33 -07:00
The Android Automerger
ddedd3a38d merge in lmp-mr1-release history after reset to c712ceeec4c15da8488c5ce143fcc6b0a02d74f3 2014-10-22 06:08:46 -07:00
The Android Automerger
75f6f21a75 merge in lmp-mr1-release history after reset to c712ceeec4c15da8488c5ce143fcc6b0a02d74f3 2014-10-21 06:08:46 -07:00
The Android Automerger
0f17126b24 merge in lmp-mr1-release history after reset to 59a02860a455af68d501ee847889620343dcfb0d 2014-10-20 06:08:44 -07:00
The Android Automerger
eca44bc1f3 merge in lmp-mr1-release history after reset to 59a02860a455af68d501ee847889620343dcfb0d 2014-10-19 06:08:38 -07:00
The Android Automerger
99415296ac merge in lmp-mr1-release history after reset to 59a02860a455af68d501ee847889620343dcfb0d 2014-10-18 06:09:03 -07:00
The Android Automerger
f020640c09 merge in lmp-mr1-release history after reset to 59a02860a455af68d501ee847889620343dcfb0d 2014-10-16 06:09:16 -07:00
The Android Automerger
466c8cbd50 merge in lmp-mr1-release history after reset to 59a02860a455af68d501ee847889620343dcfb0d 2014-10-15 06:09:02 -07:00
The Android Automerger
c9b1201be1 merge in lmp-mr1-release history after reset to 59a02860a455af68d501ee847889620343dcfb0d 2014-10-14 06:08:58 -07:00
The Android Automerger
91221be747 merge in lmp-mr1-release history after reset to e0fafb019e33374fae3fa5dc3473e921566b5991 2014-10-13 06:09:12 -07:00
The Android Automerger
d60cda85b9 merge in lmp-mr1-release history after reset to 2f25cf373ca7c875956a7c06483b30d381296817 2014-10-12 06:08:41 -07:00
The Android Automerger
50d615236d merge in lmp-mr1-release history after reset to 2f25cf373ca7c875956a7c06483b30d381296817 2014-10-11 06:08:51 -07:00
The Android Automerger
d67e1d8ae9 merge in lmp-mr1-release history after reset to e5d4fc39e3f26920f3413070d1175a0afd14a66f 2014-10-09 06:08:53 -07:00
The Android Automerger
bc9cee7f58 merge in lmp-mr1-release history after reset to e5d4fc39e3f26920f3413070d1175a0afd14a66f 2014-10-08 06:09:28 -07:00
The Android Automerger
f51bbbe319 merge in lmp-mr1-release history after reset to 6c4e16f634a8ee07fc0c3cc5299c9f7f03c5f8bf 2014-10-07 06:08:55 -07:00
The Android Automerger
26df9bf109 merge in lmp-mr1-release history after reset to 02542b3bbd6370e904e6bccba1032185b9f0eb75 2014-10-06 06:08:57 -07:00
The Android Automerger
4877fe15c2 merge in lmp-mr1-release history after reset to 02542b3bbd6370e904e6bccba1032185b9f0eb75 2014-10-05 06:08:48 -07:00
The Android Automerger
975164af3c merge in lmp-mr1-release history after reset to 22f5a61d9528219accd03dc6ed920a238088795a 2014-10-04 06:09:07 -07:00
The Android Automerger
1f5a9a4b35 merge in lmp-mr1-release history after reset to e4f8962ab5b4fb64842f4635fdf01a860bb180ee 2014-10-02 06:09:27 -07:00
The Android Automerger
dd4b377612 merge in lmp-mr1-release history after reset to aaad548535c34e2bba16b2a0b71173e0ae4b16c0 2014-10-01 06:09:15 -07:00
The Android Automerger
f9c31b1115 merge in lmp-mr1-release history after reset to aaad548535c34e2bba16b2a0b71173e0ae4b16c0 2014-09-30 06:09:53 -07:00
The Android Automerger
e09a9d77d2 merge in lmp-mr1-release history after reset to aaad548535c34e2bba16b2a0b71173e0ae4b16c0 2014-09-29 06:09:50 -07:00
The Android Automerger
bc04ede139 merge in lmp-mr1-release history after reset to aaad548535c34e2bba16b2a0b71173e0ae4b16c0 2014-09-28 06:08:54 -07:00
The Android Automerger
fe054482cc merge in lmp-mr1-release history after reset to aaad548535c34e2bba16b2a0b71173e0ae4b16c0 2014-09-27 06:09:13 -07:00
The Android Automerger
a950f53fc3 merge in lmp-mr1-release history after reset to 086bb382db3de7459bc5fad6bb1c257ca331b0e8 2014-09-25 06:09:36 -07:00
The Android Automerger
e647a62805 merge in lmp-mr1-release history after reset to 027d2717d067c3706f22bf84dc1226ede7c1566d 2014-09-24 06:09:48 -07:00
The Android Automerger
bc2fb531b7 merge in lmp-mr1-release history after reset to 027d2717d067c3706f22bf84dc1226ede7c1566d 2014-09-23 15:13:51 -07:00
The Android Automerger
460c53d4d4 merge in lmp-mr1-release history after reset to 027d2717d067c3706f22bf84dc1226ede7c1566d 2014-09-23 04:45:29 -07:00
The Android Automerger
8f0c298a3d merge in lmp-mr1-release history after reset to 027d2717d067c3706f22bf84dc1226ede7c1566d 2014-09-22 11:44:31 -07:00
The Android Automerger
d830465de8 merge in lmp-mr1-release history after reset to 027d2717d067c3706f22bf84dc1226ede7c1566d 2014-09-22 11:13:42 -07:00
The Android Automerger
306d80e339 merge in lmp-mr1-release history after reset to 027d2717d067c3706f22bf84dc1226ede7c1566d 2014-09-22 10:17:00 -07:00
The Android Automerger
6078d68321 merge in lmp-release history after reset to 027d2717d067c3706f22bf84dc1226ede7c1566d 2014-09-15 06:09:45 -07:00
The Android Automerger
277c1b00f5 merge in lmp-release history after reset to 7e00b44e80d6e38b8ab86d0ebc86b666c0ac2ef6 2014-09-14 06:09:35 -07:00
The Android Automerger
50982fd0c4 merge in lmp-release history after reset to 1d12f186edcaaf6ebd6ace1929baa23ce97a2ab8 2014-09-13 08:42:01 -07:00
The Android Automerger
25232c43fc merge in lmp-release history after reset to 7e00b44e80d6e38b8ab86d0ebc86b666c0ac2ef6 2014-09-13 06:09:46 -07:00
The Android Automerger
1d12f186ed merge in lmp-release history after reset to 33a73bfa0712c483830e4c9abbf4d6a0551478bf 2014-09-11 06:09:09 -07:00
The Android Automerger
fab4d76b46 merge in lmp-release history after reset to 7efad83d430f4d824f2aaa75edea5106f6ff8aae 2014-09-10 06:09:15 -07:00
The Android Automerger
604b2f5789 merge in lmp-release history after reset to 7efad83d430f4d824f2aaa75edea5106f6ff8aae 2014-09-09 06:09:23 -07:00
The Android Automerger
ddca20bda4 merge in lmp-release history after reset to 47ed03f70c6c9addc7f05e4ee4dc71c96d215105 2014-09-08 06:09:42 -07:00
The Android Automerger
d0beefdcd3 merge in lmp-release history after reset to 47ed03f70c6c9addc7f05e4ee4dc71c96d215105 2014-09-07 06:08:57 -07:00
The Android Automerger
ee809b90e8 merge in lmp-release history after reset to dc3814bcf916b58ec11251a530c4ecacb6e2b7c9 2014-09-06 08:50:41 -07:00
The Android Automerger
b2c6088b1e merge in lmp-release history after reset to 5beddb7d642524ecb6655ab2823caf2add679917 2014-09-06 06:08:46 -07:00
The Android Automerger
dc3814bcf9 merge in lmp-release history after reset to 1e010d60397db706cd3d1c4d5701a2bced441aa8 2014-09-04 06:09:31 -07:00
The Android Automerger
d9bead2357 merge in lmp-release history after reset to cb093d1f55701da419d1013cc3e6fbb8aea3e957 2014-09-03 06:09:05 -07:00
The Android Automerger
8c673ec8e9 merge in lmp-release history after reset to c191a8adee7ff000b6dd71ee336a12118e2a4733 2014-09-02 06:09:09 -07:00
The Android Automerger
daebe2764b merge in lmp-release history after reset to b2eb09a9ed9e08d9e49f4245d1959b2ca3fbaaf8 2014-09-01 07:54:46 -07:00
The Android Automerger
2fcb94d52c merge in lmp-release history after reset to b2eb09a9ed9e08d9e49f4245d1959b2ca3fbaaf8 2014-08-31 09:30:23 -07:00
Christopher Ferris
20dc3f8fa4 Replace snprintf calls in linker.
When enabling debug malloc, the snprintf calls in the linker fails to
update the buffer.

The problem is that snprintf makes a call to pthread_getspecific that
returns a valid pointer, but the data it points to is zero. This should
never happen and causes the snprintf to stop and do nothing.

Temporarily replace snprintf with a different implementation to work
around this issue.

Bug: 16874447
Bug: 17302493
Change-Id: I7a500f28adf153150cf2812fae745ff41f1c48d3
2014-08-27 16:12:09 -07:00
The Android Automerger
54a6221cc2 merge in lmp-release history after reset to 3f7635f4906c53fa744731efc35235456b7d93bf 2014-08-27 06:09:31 -07:00
The Android Automerger
489b5d23fd merge in lmp-release history after reset to 84d0683a824fa02dbaa6d1b56a79223804b54e80 2014-08-26 06:09:09 -07:00
The Android Automerger
5f17e16e92 merge in lmp-release history after reset to 84d0683a824fa02dbaa6d1b56a79223804b54e80 2014-08-25 06:08:46 -07:00
The Android Automerger
3bd669c605 merge in lmp-release history after reset to 84d0683a824fa02dbaa6d1b56a79223804b54e80 2014-08-24 06:08:24 -07:00
The Android Automerger
cb278332cb merge in lmp-release history after reset to 84d0683a824fa02dbaa6d1b56a79223804b54e80 2014-08-23 06:09:07 -07:00
The Android Automerger
fe9787ece9 merge in lmp-release history after reset to 1506fc178e9dcd873eaf95535ac7625ebb59388f 2014-08-21 06:09:26 -07:00
The Android Automerger
bae5898f3d merge in lmp-release history after reset to 1506fc178e9dcd873eaf95535ac7625ebb59388f 2014-08-20 06:08:54 -07:00
The Android Automerger
08f6f664ed merge in lmp-release history after reset to 6df7b609984479c894be81140730578896dbdd8f 2014-08-19 06:08:52 -07:00
Christopher Ferris
a0108accb2 Fix leak_realloc, copy entire allocation.
Bug: 16874447
Change-Id: Ie54a73fd75529961195fa5173d9116d0ae897b03
2014-08-18 14:10:28 -07:00
The Android Automerger
58df7d814e merge in lmp-release history after reset to d8e007695c755bba75b7243077271b6d655d818a 2014-08-18 06:08:40 -07:00
The Android Automerger
147ce71ddc merge in lmp-release history after reset to d8e007695c755bba75b7243077271b6d655d818a 2014-08-17 07:14:34 -07:00
The Android Automerger
2e7c8634b7 merge in lmp-release history after reset to 8a84d383fb74135e928d341baa180c55854f2f42 2014-08-14 06:09:40 -07:00
The Android Automerger
25ffdd7b9f merge in lmp-release history after reset to 72d7e667c7e926cb120c4edb53cbf74c652ab915 2014-08-13 06:10:07 -07:00
The Android Automerger
e9f34a3ee7 merge in lmp-release history after reset to 72d7e667c7e926cb120c4edb53cbf74c652ab915 2014-08-12 06:08:45 -07:00
The Android Automerger
c323d5efb8 merge in lmp-release history after reset to 72d7e667c7e926cb120c4edb53cbf74c652ab915 2014-08-11 06:08:39 +00:00
The Android Automerger
6cde02273f merge in lmp-release history after reset to 72d7e667c7e926cb120c4edb53cbf74c652ab915 2014-08-10 06:08:22 -07:00
The Android Automerger
e3ff5fca61 merge in lmp-release history after reset to f4d21fba064c398110ec0428afc0a025afb2254e 2014-08-09 06:08:34 -07:00
Christopher Ferris
b5e0854284 Add a way to disable backtracing in malloc debug.
The property libc.debug.malloc.nobacktrace set to non-zero disables
getting backtracing when using mode 1 or mode 10.

Bug: 16874447

Change-Id: I7650ba9f4385b5110b743cab01e877fc69545b3c
2014-08-08 12:49:19 -07:00
The Android Automerger
6b9b454d55 merge in lmp-release history after reset to 3e7b8e2a8bd16a37cecdae1135a5e7fc6e64c762 2014-08-07 06:08:25 -07:00
The Android Automerger
5984773a8d merge in lmp-release history after reset to db7a17d4ff56a05af01ee2fee1f3c55245bfc630 2014-08-06 06:08:43 -07:00
The Android Automerger
b4725def2e merge in lmp-release history after reset to 1b1966d9448e979d1503a3d8843708bfa8880dc6 2014-08-05 06:08:26 -07:00
The Android Automerger
b8d00ef3ba merge in lmp-release history after reset to 61833de613990f2fdaf357bb3d854d72a4980890 2014-08-04 06:08:13 -07:00
The Android Automerger
39978ccb7f merge in lmp-release history after reset to 61833de613990f2fdaf357bb3d854d72a4980890 2014-08-03 06:08:23 -07:00
The Android Automerger
6447d2f4de merge in lmp-release history after reset to 61833de613990f2fdaf357bb3d854d72a4980890 2014-08-02 06:08:40 -07:00
Christopher Ferris
1183762969 Use libunwindbacktrace for debug malloc code.
Create a method of disabling the debug allocation code paths so that
it's possible to use the libunwindbacktrace library without any
modifications.

Use this path to create and destroy the maps for the process. It's not
stricly necessary in the init code since the symbols are not modified
until after the initialize calls.

Also, remove the debug_XXX source files that doesn't need to be in libc.so.

Fix the maps reading code since it was completely broken for 64 bit.

Bug: 16408686

(cherry picked from commit 861c0ef37bcfcae56d88572cb01c18bcfe1faded)

Change-Id: I04445f0cf9a1e85172b64d57df92eb7939ce2332
2014-07-30 15:58:42 -07:00
The Android Automerger
bdf601894f merge in lmp-release history after reset to 1a5db57d5a0f633a83f20e667a4698757a63413e 2014-07-29 06:08:34 -07:00
The Android Automerger
6a20f051a2 merge in lmp-release history after reset to c1a6a7256026431a9ae49ef2a6139ea99410819b 2014-07-28 09:19:57 -07:00
The Android Automerger
8bc74887c1 merge in lmp-release history after reset to c1a6a7256026431a9ae49ef2a6139ea99410819b 2014-07-27 06:08:13 -07:00
The Android Automerger
1b710ff000 merge in lmp-release history after reset to c1a6a7256026431a9ae49ef2a6139ea99410819b 2014-07-26 06:08:31 -07:00
The Android Automerger
13fb0584e1 merge in lmp-release history after reset to c86950cb3f50ead0c9a9d0366b870d6c6e1b91c8 2014-07-24 06:08:27 -07:00
Colin Cross
4514aa630c HACK: remove %m support from printf.
The change that added this support causes a cpu hard lock on one
device.  This code clearly isn't at fault, but disabling it to
unblock until we can find a real fix.

Bug: 16484311
Change-Id: I33834dc49d959ae403b10d2c7cad12ae2950f772
2014-07-23 15:49:17 -07:00
Elliott Hughes
0caf70e98e Fix belated review comments on syslog change.
Bug: 14292866

(cherry picked from commit afe6360627ef3f0e9bc8f45535fbfae3354f3ae0)

Change-Id: I8e3cc6b37b2539e51a27261ffb5d6e58266ce11d
2014-07-23 15:49:09 -07:00
1867 changed files with 58993 additions and 343897 deletions

View File

@ -1,15 +0,0 @@
BasedOnStyle: Google
AllowShortBlocksOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
ColumnLimit: 100
CommentPragmas: NOLINT:.*
DerivePointerAlignment: false
IndentWidth: 2
ContinuationIndentWidth: 2
PointerAlignment: Left
TabWidth: 2
UseTab: Never
PenaltyExcessCharacter: 32
Cpp11BracedListStyle: false

12
ABI-bugs.txt Normal file
View File

@ -0,0 +1,12 @@
KNOWN ABI BUGS
--------------
time_t is 32-bit. http://b/5819737
off_t is 32-bit. There is off64_t, but no _FILE_OFFSET_BITS support.
sigset_t is too small on ARM and x86 (but correct on MIPS), so support
for real-time signals is broken. http://b/5828899
atexit(3) handlers registered by a shared library aren't called on
dlclose(3); this only affects ARM. http://b/4998315

View File

@ -1 +0,0 @@
subdirs = ["*"]

View File

@ -1,2 +0,0 @@
set noparent
filter=-build/header_guard,-runtime/int,-readability/function

162
HACKING.txt Normal file
View File

@ -0,0 +1,162 @@
Working on bionic
=================
What are the big pieces of bionic?
----------------------------------
libc/ --- libc.so, libc.a
The C library. Stuff like fopen(3) and kill(2).
libm/ --- libm.so, libm.a
The math library. Traditionally Unix systems kept stuff like sin(3) and
cos(3) in a separate library to save space in the days before shared
libraries.
libdl/ --- libdl.so
The dynamic linker interface library. This is actually just a bunch of
stubs that the dynamic linker replaces with pointers to its own
implementation at runtime. This is where stuff like dlopen(3) lives.
libstdc++/ --- libstdc++.so
The C++ ABI support functions. The C++ compiler doesn't know how to
implement thread-safe static initialization and the like, so it just calls
functions that are supplied by the system. Stuff like __cxa_guard_acquire
and __cxa_pure_virtual live here.
linker/ --- /system/bin/linker and /system/bin/linker64
The dynamic linker. When you run a dynamically-linked executable, its ELF
file has a DT_INTERP entry that says "use the following program to start me".
On Android, that's either linker or linker64 (depending on whether it's a
32-bit or 64-bit executable). It's responsible for loading the ELF executable
into memory and resolving references to symbols (so that when your code tries
to jump to fopen(3), say, it lands in the right place).
tests/ --- unit tests
The tests/ directory contains unit tests. Roughly arranged as one file per
publicly-exported header file.
benchmarks/ --- benchmarks
The benchmarks/ directory contains benchmarks.
What's in libc/?
----------------
libc/
arch-arm/
arch-arm64/
arch-common/
arch-mips/
arch-mips64/
arch-x86/
arch-x86_64/
# Each architecture has its own subdirectory for stuff that isn't shared
# because it's architecture-specific. There will be a .mk file in here that
# drags in all the architecture-specific files.
bionic/
# Every architecture needs a handful of machine-specific assembler files.
# They live here.
include/
machine/
# The majority of header files are actually in libc/include/, but many
# of them pull in a <machine/something.h> for things like limits,
# endianness, and how floating point numbers are represented. Those
# headers live here.
string/
# Most architectures have a handful of optional assembler files
# implementing optimized versions of various routines. The <string.h>
# functions are particular favorites.
syscalls/
# The syscalls directories contain script-generated assembler files.
# See 'Adding system calls' later.
include/
# The public header files on everyone's include path. These are a mixture of
# files written by us and files taken from BSD.
kernel/
# The kernel uapi header files. These are scrubbed copies of the originals
# in external/kernel-headers/. These files must not be edited directly. The
# generate_uapi_headers.sh script should be used to go from a kernel tree to
# external/kernel-headers/ --- this takes care of the architecture-specific
# details. The update_all.py script should be used to regenerate bionic's
# scrubbed headers from external/kernel-headers/.
private/
# These are private header files meant for use within bionic itself.
dns/
# Contains the DNS resolver (originates from NetBSD code).
upstream-dlmalloc/
upstream-freebsd/
upstream-netbsd/
upstream-openbsd/
# These directories contain unmolested upstream source. Any time we can
# just use a BSD implementation of something unmodified, we should.
# The structure under these directories mimics the upstream tree,
# but there's also...
android/
include/
# This is where we keep the hacks necessary to build BSD source
# in our world. The *-compat.h files are automatically included
# using -include, but we also provide equivalents for missing
# header/source files needed by the BSD implementation.
bionic/
# This is the biggest mess. The C++ files are files we own, typically
# because the Linux kernel interface is sufficiently different that we
# can't use any of the BSD implementations. The C files are usually
# legacy mess that needs to be sorted out, either by replacing it with
# current upstream source in one of the upstream directories or by
# switching the file to C++ and cleaning it up.
stdio/
# These are legacy files of dubious provenance. We're working to clean
# this mess up, and this directory should disappear.
tools/
# Various tools used to maintain bionic.
tzcode/
# A modified superset of the IANA tzcode. Most of the modifications relate
# to Android's use of a single file (with corresponding index) to contain
# time zone data.
zoneinfo/
# Android-format time zone data.
# See 'Updating tzdata' later.
Adding system calls
-------------------
Adding a system call usually involves:
1. Add entries to SYSCALLS.TXT.
See SYSCALLS.TXT itself for documentation on the format.
2. Run the gensyscalls.py script.
3. Add constants (and perhaps types) to the appropriate header file.
Note that you should check to see whether the constants are already in
kernel uapi header files, in which case you just need to make sure that
the appropriate POSIX header file in libc/include/ includes the
relevant file or files.
4. Add function declarations to the appropriate header file.
5. Add at least basic tests. Even a test that deliberately supplies
an invalid argument helps check that we're generating the right symbol
and have the right declaration in the header file. (And strace(1) can
confirm that the correct system call is being made.)
Updating kernel header files
----------------------------
As mentioned above, this is currently a two-step process:
1. Use generate_uapi_headers.sh to go from a Linux source tree to appropriate
contents for external/kernel-headers/.
2. Run update_all.py to scrub those headers and import them into bionic.
Updating tzdata
---------------
This is fully automated:
1. Run update-tzdata.py.

290
README.md
View File

@ -1,290 +0,0 @@
Working on bionic
=================
What are the big pieces of bionic?
----------------------------------
#### libc/ --- libc.so, libc.a
The C library. Stuff like `fopen(3)` and `kill(2)`.
#### libm/ --- libm.so, libm.a
The math library. Traditionally Unix systems kept stuff like `sin(3)` and
`cos(3)` in a separate library to save space in the days before shared
libraries.
#### libdl/ --- libdl.so
The dynamic linker interface library. This is actually just a bunch of stubs
that the dynamic linker replaces with pointers to its own implementation at
runtime. This is where stuff like `dlopen(3)` lives.
#### libstdc++/ --- libstdc++.so
The C++ ABI support functions. The C++ compiler doesn't know how to implement
thread-safe static initialization and the like, so it just calls functions that
are supplied by the system. Stuff like `__cxa_guard_acquire` and
`__cxa_pure_virtual` live here.
#### linker/ --- /system/bin/linker and /system/bin/linker64
The dynamic linker. When you run a dynamically-linked executable, its ELF file
has a `DT_INTERP` entry that says "use the following program to start me". On
Android, that's either `linker` or `linker64` (depending on whether it's a
32-bit or 64-bit executable). It's responsible for loading the ELF executable
into memory and resolving references to symbols (so that when your code tries to
jump to `fopen(3)`, say, it lands in the right place).
#### tests/ --- unit tests
The `tests/` directory contains unit tests. Roughly arranged as one file per
publicly-exported header file.
#### benchmarks/ --- benchmarks
The `benchmarks/` directory contains benchmarks.
What's in libc/?
----------------
<pre>
libc/
arch-arm/
arch-arm64/
arch-common/
arch-mips/
arch-mips64/
arch-x86/
arch-x86_64/
# Each architecture has its own subdirectory for stuff that isn't shared
# because it's architecture-specific. There will be a .mk file in here that
# drags in all the architecture-specific files.
bionic/
# Every architecture needs a handful of machine-specific assembler files.
# They live here.
include/
machine/
# The majority of header files are actually in libc/include/, but many
# of them pull in a <machine/something.h> for things like limits,
# endianness, and how floating point numbers are represented. Those
# headers live here.
string/
# Most architectures have a handful of optional assembler files
# implementing optimized versions of various routines. The <string.h>
# functions are particular favorites.
syscalls/
# The syscalls directories contain script-generated assembler files.
# See 'Adding system calls' later.
include/
# The public header files on everyone's include path. These are a mixture of
# files written by us and files taken from BSD.
kernel/
# The kernel uapi header files. These are scrubbed copies of the originals
# in external/kernel-headers/. These files must not be edited directly. The
# generate_uapi_headers.sh script should be used to go from a kernel tree to
# external/kernel-headers/ --- this takes care of the architecture-specific
# details. The update_all.py script should be used to regenerate bionic's
# scrubbed headers from external/kernel-headers/.
private/
# These are private header files meant for use within bionic itself.
dns/
# Contains the DNS resolver (originates from NetBSD code).
upstream-dlmalloc/
upstream-freebsd/
upstream-netbsd/
upstream-openbsd/
# These directories contain unmolested upstream source. Any time we can
# just use a BSD implementation of something unmodified, we should.
# The structure under these directories mimics the upstream tree,
# but there's also...
android/
include/
# This is where we keep the hacks necessary to build BSD source
# in our world. The *-compat.h files are automatically included
# using -include, but we also provide equivalents for missing
# header/source files needed by the BSD implementation.
bionic/
# This is the biggest mess. The C++ files are files we own, typically
# because the Linux kernel interface is sufficiently different that we
# can't use any of the BSD implementations. The C files are usually
# legacy mess that needs to be sorted out, either by replacing it with
# current upstream source in one of the upstream directories or by
# switching the file to C++ and cleaning it up.
stdio/
# These are legacy files of dubious provenance. We're working to clean
# this mess up, and this directory should disappear.
tools/
# Various tools used to maintain bionic.
tzcode/
# A modified superset of the IANA tzcode. Most of the modifications relate
# to Android's use of a single file (with corresponding index) to contain
# time zone data.
zoneinfo/
# Android-format time zone data.
# See 'Updating tzdata' later.
</pre>
Adding system calls
-------------------
Adding a system call usually involves:
1. Add entries to SYSCALLS.TXT.
See SYSCALLS.TXT itself for documentation on the format.
2. Run the gensyscalls.py script.
3. Add constants (and perhaps types) to the appropriate header file.
Note that you should check to see whether the constants are already in
kernel uapi header files, in which case you just need to make sure that
the appropriate POSIX header file in libc/include/ includes the
relevant file or files.
4. Add function declarations to the appropriate header file.
5. Add at least basic tests. Even a test that deliberately supplies
an invalid argument helps check that we're generating the right symbol
and have the right declaration in the header file. (And strace(1) can
confirm that the correct system call is being made.)
Updating kernel header files
----------------------------
As mentioned above, this is currently a two-step process:
1. Use generate_uapi_headers.sh to go from a Linux source tree to appropriate
contents for external/kernel-headers/.
2. Run update_all.py to scrub those headers and import them into bionic.
Updating tzdata
---------------
This is fully automated (and these days handled by the libcore team, because
they own icu, and that needs to be updated in sync with bionic):
1. Run update-tzdata.py in external/icu/tools/.
Verifying changes
-----------------
If you make a change that is likely to have a wide effect on the tree (such as a
libc header change), you should run `make checkbuild`. A regular `make` will
_not_ build the entire tree; just the minimum number of projects that are
required for the device. Tests, additional developer tools, and various other
modules will not be built. Note that `make checkbuild` will not be complete
either, as `make tests` covers a few additional modules, but generally speaking
`make checkbuild` is enough.
Running the tests
-----------------
The tests are all built from the tests/ directory.
### Device tests
$ mma
$ adb remount
$ adb sync
$ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests32
$ adb shell \
/data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static32
# Only for 64-bit targets
$ adb shell /data/nativetest64/bionic-unit-tests/bionic-unit-tests64
$ adb shell \
/data/nativetest64/bionic-unit-tests-static/bionic-unit-tests-static64
### Host tests
The host tests require that you have `lunch`ed either an x86 or x86_64 target.
$ mma
$ mm bionic-unit-tests-run-on-host32
$ mm bionic-unit-tests-run-on-host64 # For 64-bit *targets* only.
### Against glibc
As a way to check that our tests do in fact test the correct behavior (and not
just the behavior we think is correct), it is possible to run the tests against
the host's glibc. The executables are already in your path.
$ mma
$ bionic-unit-tests-glibc32
$ bionic-unit-tests-glibc64
Gathering test coverage
-----------------------
For either host or target coverage, you must first:
* `$ export NATIVE_COVERAGE=true`
* Note that the build system is ignorant to this flag being toggled, i.e. if
you change this flag, you will have to manually rebuild bionic.
* Set `bionic_coverage=true` in `libc/Android.mk` and `libm/Android.mk`.
### Coverage from device tests
$ mma
$ adb sync
$ adb shell \
GCOV_PREFIX=/data/local/tmp/gcov \
GCOV_PREFIX_STRIP=`echo $ANDROID_BUILD_TOP | grep -o / | wc -l` \
/data/nativetest/bionic-unit-tests/bionic-unit-tests32
$ acov
`acov` will pull all coverage information from the device, push it to the right
directories, run `lcov`, and open the coverage report in your browser.
### Coverage from host tests
First, build and run the host tests as usual (see above).
$ croot
$ lcov -c -d $ANDROID_PRODUCT_OUT -o coverage.info
$ genhtml -o covreport coverage.info # or lcov --list coverage.info
The coverage report is now available at `covreport/index.html`.
Attaching GDB to the tests
--------------------------
Bionic's test runner will run each test in its own process by default to prevent
tests failures from impacting other tests. This also has the added benefit of
running them in parallel, so they are much faster.
However, this also makes it difficult to run the tests under GDB. To prevent
each test from being forked, run the tests with the flag `--no-isolate`.
32-bit ABI bugs
---------------
This probably belongs in the NDK documentation rather than here, but these
are the known ABI bugs in the 32-bit ABI:
* `time_t` is 32-bit. <http://b/5819737>. In the 64-bit ABI, time_t is
64-bit.
* `off_t` is 32-bit. There is `off64_t`, and in newer releases there is
almost-complete support for `_FILE_OFFSET_BITS`. Unfortunately our stdio
implementation uses 32-bit offsets and -- worse -- function pointers to
functions that use 32-bit offsets, so there's no good way to implement
the last few pieces <http://b/24807045>. In the 64-bit ABI, off_t is
off64_t.
* `sigset_t` is too small on ARM and x86 (but correct on MIPS), so support
for real-time signals is broken. <http://b/5828899> In the 64-bit ABI,
`sigset_t` is the correct size for every architecture.

View File

@ -14,55 +14,23 @@
# limitations under the License.
#
ifneq ($(BUILD_TINY_ANDROID), true)
LOCAL_PATH := $(call my-dir)
# -----------------------------------------------------------------------------
# Benchmarks library, usable by projects outside this directory.
# -----------------------------------------------------------------------------
benchmark_cflags := \
-O2 \
-fno-builtin \
-Wall \
-Wextra \
-Werror \
-Wunused \
benchmark_cppflags := \
benchmarklib_src_files := \
Benchmark.cpp \
utils.cpp \
main.cpp \
include $(CLEAR_VARS)
LOCAL_MODULE := libbenchmark
LOCAL_CFLAGS := $(benchmark_cflags)
LOCAL_CPPFLAGS := $(benchmark_cppflags)
LOCAL_SRC_FILES := $(benchmarklib_src_files)
LOCAL_C_INCLUDES := $(benchmark_c_includes)
LOCAL_STATIC_LIBRARIES := libbase
include $(BUILD_STATIC_LIBRARY)
# Only supported on linux systems.
ifeq ($(HOST_OS),linux)
include $(CLEAR_VARS)
LOCAL_MODULE := libbenchmark
LOCAL_CFLAGS := $(benchmark_cflags)
LOCAL_CPPFLAGS := $(benchmark_cppflags)
LOCAL_SRC_FILES := $(benchmarklib_src_files)
LOCAL_C_INCLUDES := $(benchmark_c_includes)
LOCAL_MULTILIB := both
LOCAL_STATIC_LIBRARIES := libbase
include $(BUILD_HOST_STATIC_LIBRARY)
endif
# -----------------------------------------------------------------------------
# Benchmarks.
# -----------------------------------------------------------------------------
benchmark_src_files := \
benchmark_c_flags = \
-O2 \
-Wall -Wextra -Wunused \
-Werror \
-fno-builtin \
-std=gnu++11 \
benchmark_src_files = \
benchmark_main.cpp \
math_benchmark.cpp \
property_benchmark.cpp \
pthread_benchmark.cpp \
@ -73,58 +41,40 @@ benchmark_src_files := \
unistd_benchmark.cpp \
# Build benchmarks for the device (with bionic's .so). Run with:
# adb shell bionic-benchmarks32
# adb shell bionic-benchmarks64
# adb shell bionic-benchmarks
include $(CLEAR_VARS)
LOCAL_MODULE := bionic-benchmarks
LOCAL_MODULE_STEM_32 := bionic-benchmarks32
LOCAL_MODULE_STEM_64 := bionic-benchmarks64
LOCAL_MULTILIB := both
LOCAL_CFLAGS := $(benchmark_cflags)
LOCAL_CPPFLAGS := $(benchmark_cppflags)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_CFLAGS += $(benchmark_c_flags)
LOCAL_C_INCLUDES += external/stlport/stlport bionic/ bionic/libstdc++/include
LOCAL_SHARED_LIBRARIES += libstlport
LOCAL_SRC_FILES := $(benchmark_src_files)
LOCAL_STATIC_LIBRARIES := libbenchmark libbase
include $(BUILD_EXECUTABLE)
# We don't build a static benchmark executable because it's not usually
# useful. If you're trying to run the current benchmarks on an older
# release, it's (so far at least) always because you want to measure the
# performance of the old release's libc, and a static benchmark isn't
# going to let you do that.
# Only supported on linux systems.
ifeq ($(HOST_OS),linux)
# Build benchmarks for the host (against glibc!). Run with:
include $(CLEAR_VARS)
LOCAL_MODULE := bionic-benchmarks-glibc
LOCAL_MODULE_STEM_32 := bionic-benchmarks-glibc32
LOCAL_MODULE_STEM_64 := bionic-benchmarks-glibc64
LOCAL_MULTILIB := both
LOCAL_CFLAGS := $(benchmark_cflags)
LOCAL_CPPFLAGS := $(benchmark_cppflags)
LOCAL_LDFLAGS := -lrt
LOCAL_SRC_FILES := $(benchmark_src_files)
LOCAL_STATIC_LIBRARIES := libbenchmark libbase
include $(BUILD_HOST_EXECUTABLE)
endif
ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
include $(LOCAL_PATH)/../build/run-on-host.mk
ifeq ($(TARGET_ARCH),x86)
LINKER = linker
NATIVE_SUFFIX=32
else
LINKER = linker64
NATIVE_SUFFIX=64
endif
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86 x86_64))
bionic-benchmarks-run-on-host32: bionic-benchmarks bionic-prepare-run-on-host
bionic-benchmarks-run-on-host: bionic-benchmarks $(TARGET_OUT_EXECUTABLES)/$(LINKER) $(TARGET_OUT_EXECUTABLES)/sh
if [ ! -d /system -o ! -d /system/bin ]; then \
echo "Attempting to create /system/bin"; \
sudo mkdir -p -m 0777 /system/bin; \
fi
mkdir -p $(TARGET_OUT_DATA)/local/tmp
cp $(TARGET_OUT_EXECUTABLES)/$(LINKER) /system/bin
cp $(TARGET_OUT_EXECUTABLES)/sh /system/bin
ANDROID_DATA=$(TARGET_OUT_DATA) \
ANDROID_ROOT=$(TARGET_OUT) \
$(TARGET_OUT_EXECUTABLES)/bionic-benchmarks32 $(BIONIC_BENCHMARKS_FLAGS)
endif
LD_LIBRARY_PATH=$(TARGET_OUT_SHARED_LIBRARIES) \
$(TARGET_OUT_EXECUTABLES)/bionic-benchmarks$(NATIVE_SUFFIX) $(BIONIC_BENCHMARKS_FLAGS)
endif # linux-x86
ifeq ($(TARGET_IS_64_BIT),true)
bionic-benchmarks-run-on-host64: bionic-benchmarks bionic-prepare-run-on-host
ANDROID_DATA=$(TARGET_OUT_DATA) \
ANDROID_ROOT=$(TARGET_OUT) \
$(TARGET_OUT_EXECUTABLES)/bionic-benchmarks64 $(BIONIC_BENCHMARKS_FLAGS)
endif
endif
endif # !BUILD_TINY_ANDROID

View File

@ -1,159 +0,0 @@
/*
* Copyright (C) 2012 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.
*/
#include <inttypes.h>
#include <regex.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <string>
#include <vector>
#include <android-base/stringprintf.h>
#include <benchmark/Benchmark.h>
#include "utils.h"
namespace testing {
static uint64_t NanoTime() {
struct timespec t;
t.tv_sec = t.tv_nsec = 0;
clock_gettime(CLOCK_MONOTONIC, &t);
return static_cast<uint64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
}
bool Benchmark::header_printed_;
std::vector<Benchmark*>& Benchmark::List() {
static std::vector<Benchmark*> list;
return list;
}
int Benchmark::MaxNameColumnWidth() {
size_t max = 20;
for (auto& benchmark : List()) {
max = std::max(max, benchmark->NameColumnWidth());
}
return static_cast<int>(max);
}
size_t Benchmark::RunAll(std::vector<regex_t*>& regs) {
size_t benchmarks_run = 0;
header_printed_ = false;
for (auto& benchmark : List()) {
benchmarks_run += benchmark->RunAllArgs(regs);
}
return benchmarks_run;
}
void Benchmark::PrintHeader() {
if (!header_printed_) {
printf("%-*s %10s %10s\n", MaxNameColumnWidth(), "", "iterations", "ns/op");
header_printed_ = true;
}
}
template <typename T>
bool BenchmarkT<T>::ShouldRun(std::vector<regex_t*>& regs, T arg) {
if (regs.empty()) {
return true;
}
for (const auto& re : regs) {
if (regexec(re, GetNameStr(arg).c_str(), 0, NULL, 0) != REG_NOMATCH) {
return true;
}
}
return false;
}
void Benchmark::StopBenchmarkTiming() {
if (start_time_ns_ != 0) {
total_time_ns_ += NanoTime() - start_time_ns_;
}
start_time_ns_ = 0;
}
void Benchmark::StartBenchmarkTiming() {
if (start_time_ns_ == 0) {
start_time_ns_ = NanoTime();
}
}
std::string BenchmarkWithoutArg::GetNameStr(void*) {
return Name();
}
template <>
std::string BenchmarkWithArg<int>::GetNameStr(int arg) {
return Name() + "/" + PrettyInt(arg, 2);
}
template <>
std::string BenchmarkWithArg<double>::GetNameStr(double arg) {
return Name() + "/" + android::base::StringPrintf("%0.6f", arg);
}
template<typename T>
void BenchmarkT<T>::RunWithArg(T arg) {
int new_iterations = 1;
int iterations;
while (new_iterations < 1e8) {
bytes_processed_ = 0;
total_time_ns_ = 0;
start_time_ns_ = 0;
iterations = new_iterations;
RunIterations(iterations, arg);
if (total_time_ns_ >= 1e9) {
break;
}
if (total_time_ns_/iterations == 0) {
new_iterations = 1e9;
} else {
new_iterations = 1e9/ (total_time_ns_/iterations);
}
new_iterations = std::max(iterations + 1,
std::min(new_iterations + new_iterations/2, 100*iterations));
new_iterations = Round(new_iterations);
}
printf("%-*s %10s %10" PRId64, MaxNameColumnWidth(), GetNameStr(arg).c_str(),
PrettyInt(iterations, 10).c_str(), total_time_ns_/iterations);
if (total_time_ns_ > 0 && bytes_processed_ > 0) {
double gib_processed = static_cast<double>(bytes_processed_)/1e9;
double seconds = static_cast<double>(total_time_ns_)/1e9;
printf(" %8.3f GiB/s", gib_processed/seconds);
}
printf("\n");
fflush(stdout);
}
template class BenchmarkT<int>;
template class BenchmarkT<double>;
template class BenchmarkT<void*>;
template class BenchmarkWithArg<int>;
template class BenchmarkWithArg<double>;
} // namespace testing

61
benchmarks/benchmark.h Normal file
View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2012 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.
*/
#include <stdint.h>
#include <vector>
namespace testing {
class Benchmark {
public:
Benchmark(const char* name, void (*fn)(int)) {
Register(name, fn, NULL);
}
Benchmark(const char* name, void (*fn_range)(int, int)) {
Register(name, NULL, fn_range);
}
Benchmark* Arg(int x);
const char* Name();
bool ShouldRun(int argc, char* argv[]);
void Run();
private:
const char* name_;
void (*fn_)(int);
void (*fn_range_)(int, int);
std::vector<int> args_;
void Register(const char* name, void (*fn)(int), void (*fn_range)(int, int));
void RunRepeatedlyWithArg(int iterations, int arg);
void RunWithArg(int arg);
};
} // namespace testing
void SetBenchmarkBytesProcessed(int64_t);
void StopBenchmarkTiming();
void StartBenchmarkTiming();
#define BENCHMARK(f) \
static ::testing::Benchmark* _benchmark_##f __attribute__((unused)) = \
(new ::testing::Benchmark(#f, f))

View File

@ -1,169 +0,0 @@
/*
* Copyright (C) 2012 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.
*/
#ifndef BENCHMARKS_BENCHMARK_H_
#define BENCHMARKS_BENCHMARK_H_
#include <regex.h>
#include <stdint.h>
#include <string>
#include <vector>
namespace testing {
class Benchmark {
public:
Benchmark() {
List().push_back(this);
}
virtual ~Benchmark() {}
virtual std::string Name() = 0;
virtual size_t RunAllArgs(std::vector<regex_t*>&) = 0;
void SetBenchmarkBytesProcessed(uint64_t bytes) { bytes_processed_ += bytes; }
void StopBenchmarkTiming();
void StartBenchmarkTiming();
// Run all of the benchmarks that have registered.
static size_t RunAll(std::vector<regex_t*>&);
static std::vector<Benchmark*>& List();
static int MaxNameColumnWidth();
protected:
virtual size_t NameColumnWidth() = 0;
uint64_t bytes_processed_;
uint64_t total_time_ns_;
uint64_t start_time_ns_;
static bool header_printed_;
static void PrintHeader();
};
template <typename T>
class BenchmarkT : public Benchmark {
public:
BenchmarkT() {}
virtual ~BenchmarkT() {}
protected:
bool ShouldRun(std::vector<regex_t*>&, T arg);
void RunWithArg(T arg);
virtual void RunIterations(int, T) = 0;
virtual std::string GetNameStr(T) = 0;
};
class BenchmarkWithoutArg : public BenchmarkT<void*> {
public:
BenchmarkWithoutArg() {}
virtual ~BenchmarkWithoutArg() {}
protected:
virtual size_t RunAllArgs(std::vector<regex_t*>& regs) override {
size_t benchmarks_run = 0;
if (BenchmarkT<void*>::ShouldRun(regs, nullptr)) {
PrintHeader();
RunWithArg(nullptr);
benchmarks_run++;
}
return benchmarks_run;
}
virtual void RunIterations(int iters, void*) override {
Run(iters);
}
virtual void Run(int) = 0;
virtual size_t NameColumnWidth() override {
return Name().size();
}
virtual std::string GetNameStr(void *) override;
};
template<typename T>
class BenchmarkWithArg : public BenchmarkT<T> {
public:
BenchmarkWithArg() {}
virtual ~BenchmarkWithArg() {}
BenchmarkWithArg* Arg(T arg) {
args_.push_back(arg);
return this;
}
protected:
virtual size_t NameColumnWidth() override {
size_t max = 0;
for (const auto& arg : args_) {
max = std::max(max, GetNameStr(arg).size());
}
return max;
}
std::string GetNameStr(T arg) override;
virtual size_t RunAllArgs(std::vector<regex_t*>& regs) override {
size_t benchmarks_run = 0;
for (T& arg : args_) {
if (BenchmarkT<T>::ShouldRun(regs, arg)) {
Benchmark::PrintHeader();
BenchmarkT<T>::RunWithArg(arg);
benchmarks_run++;
}
}
return benchmarks_run;
}
virtual void RunIterations(int iters, T arg) override {
Run(iters, arg);
}
virtual void Run(int iters, T arg) = 0;
private:
std::vector<T> args_;
};
} // namespace testing
#define BENCHMARK_START(f, super_class) \
class f : public super_class { \
public: \
f() {} \
virtual ~f() {} \
virtual std::string Name() override { return #f; } \
#define BENCHMARK_NO_ARG(f) \
BENCHMARK_START(f, ::testing::BenchmarkWithoutArg) \
virtual void Run(int) override; \
}; \
static ::testing::Benchmark* __benchmark_##f = new f()
#define BENCHMARK_WITH_ARG(f, arg_type) \
BENCHMARK_START(f, ::testing::BenchmarkWithArg<arg_type>) \
virtual void Run(int, arg_type) override; \
}; \
static ::testing::BenchmarkWithArg<arg_type>* __benchmark_##f = (new f())
#endif // BENCHMARKS_BENCHMARK_H_

View File

@ -0,0 +1,226 @@
/*
* Copyright (C) 2012 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.
*/
#include "benchmark.h"
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <map>
#include <inttypes.h>
static int64_t g_bytes_processed;
static int64_t g_benchmark_total_time_ns;
static int64_t g_benchmark_start_time_ns;
typedef std::map<std::string, ::testing::Benchmark*> BenchmarkMap;
typedef BenchmarkMap::iterator BenchmarkMapIt;
static BenchmarkMap g_benchmarks;
static int g_name_column_width = 20;
static int Round(int n) {
int base = 1;
while (base*10 < n) {
base *= 10;
}
if (n < 2*base) {
return 2*base;
}
if (n < 5*base) {
return 5*base;
}
return 10*base;
}
static int64_t NanoTime() {
struct timespec t;
t.tv_sec = t.tv_nsec = 0;
clock_gettime(CLOCK_MONOTONIC, &t);
return static_cast<int64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
}
namespace testing {
Benchmark* Benchmark::Arg(int arg) {
args_.push_back(arg);
return this;
}
const char* Benchmark::Name() {
return name_;
}
bool Benchmark::ShouldRun(int argc, char* argv[]) {
if (argc == 1) {
return true; // With no arguments, we run all benchmarks.
}
// Otherwise, we interpret each argument as a regular expression and
// see if any of our benchmarks match.
for (int i = 1; i < argc; i++) {
regex_t re;
if (regcomp(&re, argv[i], 0) != 0) {
fprintf(stderr, "couldn't compile \"%s\" as a regular expression!\n", argv[i]);
exit(EXIT_FAILURE);
}
int match = regexec(&re, name_, 0, NULL, 0);
regfree(&re);
if (match != REG_NOMATCH) {
return true;
}
}
return false;
}
void Benchmark::Register(const char* name, void (*fn)(int), void (*fn_range)(int, int)) {
name_ = name;
fn_ = fn;
fn_range_ = fn_range;
if (fn_ == NULL && fn_range_ == NULL) {
fprintf(stderr, "%s: missing function\n", name_);
exit(EXIT_FAILURE);
}
g_benchmarks.insert(std::make_pair(name, this));
}
void Benchmark::Run() {
if (fn_ != NULL) {
RunWithArg(0);
} else {
if (args_.empty()) {
fprintf(stderr, "%s: no args!\n", name_);
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < args_.size(); ++i) {
RunWithArg(args_[i]);
}
}
}
void Benchmark::RunRepeatedlyWithArg(int iterations, int arg) {
g_bytes_processed = 0;
g_benchmark_total_time_ns = 0;
g_benchmark_start_time_ns = NanoTime();
if (fn_ != NULL) {
fn_(iterations);
} else {
fn_range_(iterations, arg);
}
if (g_benchmark_start_time_ns != 0) {
g_benchmark_total_time_ns += NanoTime() - g_benchmark_start_time_ns;
}
}
void Benchmark::RunWithArg(int arg) {
// run once in case it's expensive
int iterations = 1;
RunRepeatedlyWithArg(iterations, arg);
while (g_benchmark_total_time_ns < 1e9 && iterations < 1e9) {
int last = iterations;
if (g_benchmark_total_time_ns/iterations == 0) {
iterations = 1e9;
} else {
iterations = 1e9 / (g_benchmark_total_time_ns/iterations);
}
iterations = std::max(last + 1, std::min(iterations + iterations/2, 100*last));
iterations = Round(iterations);
RunRepeatedlyWithArg(iterations, arg);
}
char throughput[100];
throughput[0] = '\0';
if (g_benchmark_total_time_ns > 0 && g_bytes_processed > 0) {
double mib_processed = static_cast<double>(g_bytes_processed)/1e6;
double seconds = static_cast<double>(g_benchmark_total_time_ns)/1e9;
snprintf(throughput, sizeof(throughput), " %8.2f MiB/s", mib_processed/seconds);
}
char full_name[100];
if (fn_range_ != NULL) {
if (arg >= (1<<20)) {
snprintf(full_name, sizeof(full_name), "%s/%dM", name_, arg/(1<<20));
} else if (arg >= (1<<10)) {
snprintf(full_name, sizeof(full_name), "%s/%dK", name_, arg/(1<<10));
} else {
snprintf(full_name, sizeof(full_name), "%s/%d", name_, arg);
}
} else {
snprintf(full_name, sizeof(full_name), "%s", name_);
}
printf("%-*s %10d %10" PRId64 "%s\n", g_name_column_width, full_name,
iterations, g_benchmark_total_time_ns/iterations, throughput);
fflush(stdout);
}
} // namespace testing
void SetBenchmarkBytesProcessed(int64_t x) {
g_bytes_processed = x;
}
void StopBenchmarkTiming() {
if (g_benchmark_start_time_ns != 0) {
g_benchmark_total_time_ns += NanoTime() - g_benchmark_start_time_ns;
}
g_benchmark_start_time_ns = 0;
}
void StartBenchmarkTiming() {
if (g_benchmark_start_time_ns == 0) {
g_benchmark_start_time_ns = NanoTime();
}
}
int main(int argc, char* argv[]) {
if (g_benchmarks.empty()) {
fprintf(stderr, "No benchmarks registered!\n");
exit(EXIT_FAILURE);
}
for (BenchmarkMapIt it = g_benchmarks.begin(); it != g_benchmarks.end(); ++it) {
int name_width = static_cast<int>(strlen(it->second->Name()));
g_name_column_width = std::max(g_name_column_width, name_width);
}
bool need_header = true;
for (BenchmarkMapIt it = g_benchmarks.begin(); it != g_benchmarks.end(); ++it) {
::testing::Benchmark* b = it->second;
if (b->ShouldRun(argc, argv)) {
if (need_header) {
printf("%-*s %10s %10s\n", g_name_column_width, "", "iterations", "ns/op");
fflush(stdout);
need_header = false;
}
b->Run();
}
}
if (need_header) {
fprintf(stderr, "No matching benchmarks!\n");
fprintf(stderr, "Available benchmarks:\n");
for (BenchmarkMapIt it = g_benchmarks.begin(); it != g_benchmarks.end(); ++it) {
fprintf(stderr, " %s\n", it->second->Name());
}
exit(EXIT_FAILURE);
}
return 0;
}

View File

@ -1,61 +0,0 @@
/*
* Copyright (C) 2012 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.
*/
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <benchmark/Benchmark.h>
int main(int argc, char* argv[]) {
if (::testing::Benchmark::List().empty()) {
fprintf(stderr, "No benchmarks registered!\n");
exit(EXIT_FAILURE);
}
std::vector<regex_t*> regs;
for (int i = 1; i < argc; i++) {
regex_t* re = new regex_t;
int errcode = regcomp(re, argv[i], 0);
if (errcode != 0) {
size_t errbuf_size = regerror(errcode, re, NULL, 0);
if (errbuf_size > 0) {
char* errbuf = new char[errbuf_size];
regerror(errcode, re, errbuf, errbuf_size);
fprintf(stderr, "Couldn't compile \"%s\" as a regular expression: %s\n",
argv[i], errbuf);
} else {
fprintf(stderr, "Unknown compile error for \"%s\" as a regular expression!\n", argv[i]);
}
exit(EXIT_FAILURE);
}
regs.push_back(re);
}
if (::testing::Benchmark::RunAll(regs) == 0) {
fprintf(stderr, "No matching benchmarks!\n");
fprintf(stderr, "Available benchmarks:\n");
for (const auto& benchmark : ::testing::Benchmark::List()) {
fprintf(stderr, " %s\n", benchmark->Name().c_str());
}
exit(EXIT_FAILURE);
}
return 0;
}

View File

@ -14,20 +14,16 @@
* limitations under the License.
*/
#include "benchmark.h"
#include <fenv.h>
#include <math.h>
#include <benchmark/Benchmark.h>
#define AT_COMMON_VALS \
Arg(1234.0)->Arg(nan(""))->Arg(HUGE_VAL)->Arg(0.0)
// Avoid optimization.
volatile double d;
volatile double v;
double d;
double v;
BENCHMARK_NO_ARG(BM_math_sqrt);
void BM_math_sqrt::Run(int iters) {
static void BM_math_sqrt(int iters) {
StartBenchmarkTiming();
d = 0.0;
@ -38,9 +34,9 @@ void BM_math_sqrt::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_math_sqrt);
BENCHMARK_NO_ARG(BM_math_log10);
void BM_math_log10::Run(int iters) {
static void BM_math_log10(int iters) {
StartBenchmarkTiming();
d = 0.0;
@ -51,9 +47,9 @@ void BM_math_log10::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_math_log10);
BENCHMARK_NO_ARG(BM_math_logb);
void BM_math_logb::Run(int iters) {
static void BM_math_logb(int iters) {
StartBenchmarkTiming();
d = 0.0;
@ -64,120 +60,61 @@ void BM_math_logb::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_math_logb);
BENCHMARK_WITH_ARG(BM_math_isfinite_macro, double)->AT_COMMON_VALS;
void BM_math_isfinite_macro::Run(int iters, double value) {
static void BM_math_isinf_NORMAL(int iters) {
StartBenchmarkTiming();
d = 0.0;
v = value;
for (int i = 0; i < iters; ++i) {
d += isfinite(v);
}
StopBenchmarkTiming();
}
#if defined(__BIONIC__)
#define test_isfinite __isfinite
#else
#define test_isfinite __finite
#endif
BENCHMARK_WITH_ARG(BM_math_isfinite, double)->AT_COMMON_VALS;
void BM_math_isfinite::Run(int iters, double value) {
StartBenchmarkTiming();
d = 0.0;
v = value;
for (int i = 0; i < iters; ++i) {
d += test_isfinite(v);
}
StopBenchmarkTiming();
}
BENCHMARK_WITH_ARG(BM_math_isinf_macro, double)->AT_COMMON_VALS;
void BM_math_isinf_macro::Run(int iters, double value) {
StartBenchmarkTiming();
d = 0.0;
v = value;
for (int i = 0; i < iters; ++i) {
d += isinf(v);
}
StopBenchmarkTiming();
}
BENCHMARK_WITH_ARG(BM_math_isinf, double)->AT_COMMON_VALS;
void BM_math_isinf::Run(int iters, double value) {
StartBenchmarkTiming();
d = 0.0;
v = value;
v = 1234.0; // FP_NORMAL
for (int i = 0; i < iters; ++i) {
d += (isinf)(v);
}
StopBenchmarkTiming();
}
BENCHMARK(BM_math_isinf_NORMAL);
BENCHMARK_WITH_ARG(BM_math_isnan_macro, double)->AT_COMMON_VALS;
void BM_math_isnan_macro::Run(int iters, double value) {
static void BM_math_isinf_NAN(int iters) {
StartBenchmarkTiming();
d = 0.0;
v = value;
v = nan(""); // FP_NAN
for (int i = 0; i < iters; ++i) {
d += isnan(v);
d += (isinf)(v);
}
StopBenchmarkTiming();
}
BENCHMARK(BM_math_isinf_NAN);
BENCHMARK_WITH_ARG(BM_math_isnan, double)->AT_COMMON_VALS;
void BM_math_isnan::Run(int iters, double value) {
static void BM_math_isinf_INFINITE(int iters) {
StartBenchmarkTiming();
d = 0.0;
v = value;
v = HUGE_VAL; // FP_INFINITE
for (int i = 0; i < iters; ++i) {
d += (isnan)(v);
d += (isinf)(v);
}
StopBenchmarkTiming();
}
BENCHMARK(BM_math_isinf_INFINITE);
BENCHMARK_WITH_ARG(BM_math_isnormal_macro, double)->AT_COMMON_VALS;
void BM_math_isnormal_macro::Run(int iters, double value) {
static void BM_math_isinf_ZERO(int iters) {
StartBenchmarkTiming();
d = 0.0;
v = value;
v = 0.0; // FP_ZERO
for (int i = 0; i < iters; ++i) {
d += isnormal(v);
d += (isinf)(v);
}
StopBenchmarkTiming();
}
BENCHMARK(BM_math_isinf_ZERO);
#if defined(__BIONIC__)
BENCHMARK_WITH_ARG(BM_math_isnormal, double)->AT_COMMON_VALS;
void BM_math_isnormal::Run(int iters, double value) {
StartBenchmarkTiming();
d = 0.0;
v = value;
for (int i = 0; i < iters; ++i) {
d += (__isnormal)(v);
}
StopBenchmarkTiming();
}
#endif
BENCHMARK_NO_ARG(BM_math_sin_fast);
void BM_math_sin_fast::Run(int iters) {
static void BM_math_sin_fast(int iters) {
StartBenchmarkTiming();
d = 1.0;
@ -187,9 +124,9 @@ void BM_math_sin_fast::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_math_sin_fast);
BENCHMARK_NO_ARG(BM_math_sin_feupdateenv);
void BM_math_sin_feupdateenv::Run(int iters) {
static void BM_math_sin_feupdateenv(int iters) {
StartBenchmarkTiming();
d = 1.0;
@ -203,9 +140,9 @@ void BM_math_sin_feupdateenv::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_math_sin_feupdateenv);
BENCHMARK_NO_ARG(BM_math_sin_fesetenv);
void BM_math_sin_fesetenv::Run(int iters) {
static void BM_math_sin_fesetenv(int iters) {
StartBenchmarkTiming();
d = 1.0;
@ -219,68 +156,56 @@ void BM_math_sin_fesetenv::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_math_sin_fesetenv);
BENCHMARK_WITH_ARG(BM_math_fpclassify, double)->AT_COMMON_VALS;
void BM_math_fpclassify::Run(int iters, double value) {
static void BM_math_fpclassify_NORMAL(int iters) {
StartBenchmarkTiming();
d = 0.0;
v = value;
v = 1234.0; // FP_NORMAL
for (int i = 0; i < iters; ++i) {
d += fpclassify(v);
}
StopBenchmarkTiming();
}
BENCHMARK(BM_math_fpclassify_NORMAL);
BENCHMARK_WITH_ARG(BM_math_signbit_macro, double)->AT_COMMON_VALS;
void BM_math_signbit_macro::Run(int iters, double value) {
static void BM_math_fpclassify_NAN(int iters) {
StartBenchmarkTiming();
d = 0.0;
v = value;
v = nan(""); // FP_NAN
for (int i = 0; i < iters; ++i) {
d += signbit(v);
d += fpclassify(v);
}
StopBenchmarkTiming();
}
BENCHMARK(BM_math_fpclassify_NAN);
BENCHMARK_WITH_ARG(BM_math_signbit, double)->AT_COMMON_VALS;
void BM_math_signbit::Run(int iters, double value) {
static void BM_math_fpclassify_INFINITE(int iters) {
StartBenchmarkTiming();
d = 0.0;
v = value;
v = HUGE_VAL; // FP_INFINITE
for (int i = 0; i < iters; ++i) {
d += (__signbit)(v);
d += fpclassify(v);
}
StopBenchmarkTiming();
}
BENCHMARK(BM_math_fpclassify_INFINITE);
BENCHMARK_WITH_ARG(BM_math_fabs_macro, double)->AT_COMMON_VALS;
void BM_math_fabs_macro::Run(int iters, double value) {
static void BM_math_fpclassify_ZERO(int iters) {
StartBenchmarkTiming();
d = 0.0;
v = value;
v = 0.0; // FP_ZERO
for (int i = 0; i < iters; ++i) {
d += fabs(v);
}
StopBenchmarkTiming();
}
BENCHMARK_WITH_ARG(BM_math_fabs, double)->AT_COMMON_VALS;
void BM_math_fabs::Run(int iters, double value) {
StartBenchmarkTiming();
d = 0.0;
v = value;
for (int i = 0; i < iters; ++i) {
d += (fabs)(v);
d += fpclassify(v);
}
StopBenchmarkTiming();
}
BENCHMARK(BM_math_fpclassify_ZERO);

View File

@ -14,21 +14,19 @@
* limitations under the License.
*/
#include "benchmark.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string>
#if defined(__BIONIC__)
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
#include <benchmark/Benchmark.h>
#include <vector>
#include <string>
extern void* __system_property_area__;
extern void *__system_property_area__;
// Do not exceed 512, that is about the largest number of properties
// that can be created with the current property area size.
@ -36,198 +34,200 @@ extern void* __system_property_area__;
Arg(1)->Arg(4)->Arg(16)->Arg(64)->Arg(128)->Arg(256)->Arg(512)
struct LocalPropertyTestState {
LocalPropertyTestState(int nprops) : nprops(nprops), valid(false) {
static const char prop_name_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
LocalPropertyTestState(int nprops) : nprops(nprops), valid(false) {
static const char prop_name_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
const char* android_data = getenv("ANDROID_DATA");
if (android_data == NULL) {
printf("ANDROID_DATA environment variable not set\n");
return;
}
char dir_template[PATH_MAX];
snprintf(dir_template, sizeof(dir_template), "%s/local/tmp/prop-XXXXXX", android_data);
char* dirname = mkdtemp(dir_template);
if (!dirname) {
printf("making temp file for test state failed (is %s/local/tmp writable?): %s\n",
android_data, strerror(errno));
return;
}
old_pa = __system_property_area__;
__system_property_area__ = NULL;
pa_dirname = dirname;
pa_filename = pa_dirname + "/__properties__";
__system_property_set_filename(pa_filename.c_str());
__system_property_area_init();
names = new char* [nprops];
name_lens = new int[nprops];
values = new char* [nprops];
value_lens = new int[nprops];
srandom(nprops);
for (int i = 0; i < nprops; i++) {
// Make sure the name has at least 10 characters to make
// it very unlikely to generate the same random name.
name_lens[i] = (random() % (PROP_NAME_MAX - 10)) + 10;
names[i] = new char[PROP_NAME_MAX + 1];
size_t prop_name_len = sizeof(prop_name_chars) - 1;
for (int j = 0; j < name_lens[i]; j++) {
if (j == 0 || names[i][j-1] == '.' || j == name_lens[i] - 1) {
// Certain values are not allowed:
// - Don't start name with '.'
// - Don't allow '.' to appear twice in a row
// - Don't allow the name to end with '.'
// This assumes that '.' is the last character in the
// array so that decrementing the length by one removes
// the value from the possible values.
prop_name_len--;
const char* android_data = getenv("ANDROID_DATA");
if (android_data == NULL) {
printf("ANDROID_DATA environment variable not set\n");
return;
}
char dir_template[PATH_MAX];
snprintf(dir_template, sizeof(dir_template), "%s/local/tmp/prop-XXXXXX", android_data);
char *dirname = mkdtemp(dir_template);
if (!dirname) {
printf("making temp file for test state failed (is %s/local/tmp writable?): %s\n",
android_data, strerror(errno));
return;
}
names[i][j] = prop_name_chars[random() % prop_name_len];
}
names[i][name_lens[i]] = 0;
// Make sure the value contains at least 1 character.
value_lens[i] = (random() % (PROP_VALUE_MAX - 1)) + 1;
values[i] = new char[PROP_VALUE_MAX];
for (int j = 0; j < value_lens[i]; j++) {
values[i][j] = prop_name_chars[random() % (sizeof(prop_name_chars) - 1)];
}
old_pa = __system_property_area__;
__system_property_area__ = NULL;
if (__system_property_add(names[i], name_lens[i], values[i], value_lens[i]) < 0) {
printf("Failed to add a property, terminating...\n");
printf("%s = %.*s\n", names[i], value_lens[i], values[i]);
exit(1);
}
pa_dirname = dirname;
pa_filename = pa_dirname + "/__properties__";
__system_property_set_filename(pa_filename.c_str());
__system_property_area_init();
names = new char* [nprops];
name_lens = new int[nprops];
values = new char* [nprops];
value_lens = new int[nprops];
srandom(nprops);
for (int i = 0; i < nprops; i++) {
// Make sure the name has at least 10 characters to make
// it very unlikely to generate the same random name.
name_lens[i] = (random() % (PROP_NAME_MAX - 10)) + 10;
names[i] = new char[PROP_NAME_MAX + 1];
size_t prop_name_len = sizeof(prop_name_chars) - 1;
for (int j = 0; j < name_lens[i]; j++) {
if (j == 0 || names[i][j-1] == '.' || j == name_lens[i] - 1) {
// Certain values are not allowed:
// - Don't start name with '.'
// - Don't allow '.' to appear twice in a row
// - Don't allow the name to end with '.'
// This assumes that '.' is the last character in the
// array so that decrementing the length by one removes
// the value from the possible values.
prop_name_len--;
}
names[i][j] = prop_name_chars[random() % prop_name_len];
}
names[i][name_lens[i]] = 0;
// Make sure the value contains at least 1 character.
value_lens[i] = (random() % (PROP_VALUE_MAX - 1)) + 1;
values[i] = new char[PROP_VALUE_MAX];
for (int j = 0; j < value_lens[i]; j++) {
values[i][j] = prop_name_chars[random() % (sizeof(prop_name_chars) - 1)];
}
if (__system_property_add(names[i], name_lens[i], values[i], value_lens[i]) < 0) {
printf("Failed to add a property, terminating...\n");
printf("%s = %.*s\n", names[i], value_lens[i], values[i]);
exit(1);
}
}
valid = true;
}
valid = true;
}
~LocalPropertyTestState() {
if (!valid)
return;
~LocalPropertyTestState() {
if (!valid)
return;
__system_property_area__ = old_pa;
__system_property_area__ = old_pa;
__system_property_set_filename(PROP_FILENAME);
unlink(pa_filename.c_str());
rmdir(pa_dirname.c_str());
__system_property_set_filename(PROP_FILENAME);
unlink(pa_filename.c_str());
rmdir(pa_dirname.c_str());
for (int i = 0; i < nprops; i++) {
delete names[i];
delete values[i];
for (int i = 0; i < nprops; i++) {
delete names[i];
delete values[i];
}
delete[] names;
delete[] name_lens;
delete[] values;
delete[] value_lens;
}
delete[] names;
delete[] name_lens;
delete[] values;
delete[] value_lens;
}
public:
const int nprops;
char** names;
int* name_lens;
char** values;
int* value_lens;
bool valid;
const int nprops;
char **names;
int *name_lens;
char **values;
int *value_lens;
bool valid;
private:
std::string pa_dirname;
std::string pa_filename;
void* old_pa;
std::string pa_dirname;
std::string pa_filename;
void *old_pa;
};
BENCHMARK_WITH_ARG(BM_property_get, int)->TEST_NUM_PROPS;
void BM_property_get::Run(int iters, int nprops) {
StopBenchmarkTiming();
static void BM_property_get(int iters, int nprops)
{
StopBenchmarkTiming();
LocalPropertyTestState pa(nprops);
char value[PROP_VALUE_MAX];
LocalPropertyTestState pa(nprops);
char value[PROP_VALUE_MAX];
if (!pa.valid)
return;
if (!pa.valid)
return;
srandom(iters * nprops);
srandom(iters * nprops);
StartBenchmarkTiming();
StartBenchmarkTiming();
for (int i = 0; i < iters; i++) {
__system_property_get(pa.names[random() % nprops], value);
}
StopBenchmarkTiming();
for (int i = 0; i < iters; i++) {
__system_property_get(pa.names[random() % nprops], value);
}
StopBenchmarkTiming();
}
BENCHMARK(BM_property_get)->TEST_NUM_PROPS;
BENCHMARK_WITH_ARG(BM_property_find, int)->TEST_NUM_PROPS;
void BM_property_find::Run(int iters, int nprops) {
StopBenchmarkTiming();
static void BM_property_find(int iters, int nprops)
{
StopBenchmarkTiming();
LocalPropertyTestState pa(nprops);
LocalPropertyTestState pa(nprops);
if (!pa.valid)
return;
if (!pa.valid)
return;
srandom(iters * nprops);
srandom(iters * nprops);
StartBenchmarkTiming();
StartBenchmarkTiming();
for (int i = 0; i < iters; i++) {
__system_property_find(pa.names[random() % nprops]);
}
StopBenchmarkTiming();
for (int i = 0; i < iters; i++) {
__system_property_find(pa.names[random() % nprops]);
}
StopBenchmarkTiming();
}
BENCHMARK(BM_property_find)->TEST_NUM_PROPS;
BENCHMARK_WITH_ARG(BM_property_read, int)->TEST_NUM_PROPS;
void BM_property_read::Run(int iters, int nprops) {
StopBenchmarkTiming();
static void BM_property_read(int iters, int nprops)
{
StopBenchmarkTiming();
LocalPropertyTestState pa(nprops);
LocalPropertyTestState pa(nprops);
if (!pa.valid)
return;
if (!pa.valid)
return;
srandom(iters * nprops);
const prop_info** pinfo = new const prop_info*[iters];
char propvalue[PROP_VALUE_MAX];
srandom(iters * nprops);
const prop_info** pinfo = new const prop_info*[iters];
char propvalue[PROP_VALUE_MAX];
for (int i = 0; i < iters; i++) {
pinfo[i] = __system_property_find(pa.names[random() % nprops]);
}
for (int i = 0; i < iters; i++) {
pinfo[i] = __system_property_find(pa.names[random() % nprops]);
}
StartBenchmarkTiming();
for (int i = 0; i < iters; i++) {
__system_property_read(pinfo[i], 0, propvalue);
}
StopBenchmarkTiming();
StartBenchmarkTiming();
for (int i = 0; i < iters; i++) {
__system_property_read(pinfo[i], 0, propvalue);
}
StopBenchmarkTiming();
delete[] pinfo;
delete[] pinfo;
}
BENCHMARK(BM_property_read)->TEST_NUM_PROPS;
BENCHMARK_WITH_ARG(BM_property_serial, int)->TEST_NUM_PROPS;
void BM_property_serial::Run(int iters, int nprops) {
StopBenchmarkTiming();
static void BM_property_serial(int iters, int nprops)
{
StopBenchmarkTiming();
LocalPropertyTestState pa(nprops);
LocalPropertyTestState pa(nprops);
if (!pa.valid)
return;
if (!pa.valid)
return;
srandom(iters * nprops);
const prop_info** pinfo = new const prop_info*[iters];
srandom(iters * nprops);
const prop_info** pinfo = new const prop_info*[iters];
for (int i = 0; i < iters; i++) {
pinfo[i] = __system_property_find(pa.names[random() % nprops]);
}
for (int i = 0; i < iters; i++) {
pinfo[i] = __system_property_find(pa.names[random() % nprops]);
}
StartBenchmarkTiming();
for (int i = 0; i < iters; i++) {
__system_property_serial(pinfo[i]);
}
StopBenchmarkTiming();
StartBenchmarkTiming();
for (int i = 0; i < iters; i++) {
__system_property_serial(pinfo[i]);
}
StopBenchmarkTiming();
delete[] pinfo;
delete[] pinfo;
}
#endif // __BIONIC__
BENCHMARK(BM_property_serial)->TEST_NUM_PROPS;

View File

@ -14,15 +14,14 @@
* limitations under the License.
*/
#include <pthread.h>
#include "benchmark.h"
#include <benchmark/Benchmark.h>
#include <pthread.h>
// Stop GCC optimizing out our pure function.
/* Must not be static! */ pthread_t (*pthread_self_fp)() = pthread_self;
BENCHMARK_NO_ARG(BM_pthread_self);
void BM_pthread_self::Run(int iters) {
static void BM_pthread_self(int iters) {
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
@ -31,9 +30,9 @@ void BM_pthread_self::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_pthread_self);
BENCHMARK_NO_ARG(BM_pthread_getspecific);
void BM_pthread_getspecific::Run(int iters) {
static void BM_pthread_getspecific(int iters) {
StopBenchmarkTiming();
pthread_key_t key;
pthread_key_create(&key, NULL);
@ -46,27 +45,12 @@ void BM_pthread_getspecific::Run(int iters) {
StopBenchmarkTiming();
pthread_key_delete(key);
}
BENCHMARK_NO_ARG(BM_pthread_setspecific);
void BM_pthread_setspecific::Run(int iters) {
StopBenchmarkTiming();
pthread_key_t key;
pthread_key_create(&key, NULL);
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
pthread_setspecific(key, NULL);
}
StopBenchmarkTiming();
pthread_key_delete(key);
}
BENCHMARK(BM_pthread_getspecific);
static void DummyPthreadOnceInitFunction() {
}
BENCHMARK_NO_ARG(BM_pthread_once);
void BM_pthread_once::Run(int iters) {
static void BM_pthread_once(int iters) {
StopBenchmarkTiming();
pthread_once_t once = PTHREAD_ONCE_INIT;
pthread_once(&once, DummyPthreadOnceInitFunction);
@ -78,9 +62,9 @@ void BM_pthread_once::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_pthread_once);
BENCHMARK_NO_ARG(BM_pthread_mutex_lock);
void BM_pthread_mutex_lock::Run(int iters) {
static void BM_pthread_mutex_lock(int iters) {
StopBenchmarkTiming();
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
StartBenchmarkTiming();
@ -92,11 +76,11 @@ void BM_pthread_mutex_lock::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_pthread_mutex_lock);
BENCHMARK_NO_ARG(BM_pthread_mutex_lock_ERRORCHECK);
void BM_pthread_mutex_lock_ERRORCHECK::Run(int iters) {
static void BM_pthread_mutex_lock_ERRORCHECK(int iters) {
StopBenchmarkTiming();
pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER;
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
@ -106,11 +90,11 @@ void BM_pthread_mutex_lock_ERRORCHECK::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK);
BENCHMARK_NO_ARG(BM_pthread_mutex_lock_RECURSIVE);
void BM_pthread_mutex_lock_RECURSIVE::Run(int iters) {
static void BM_pthread_mutex_lock_RECURSIVE(int iters) {
StopBenchmarkTiming();
pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
@ -120,114 +104,4 @@ void BM_pthread_mutex_lock_RECURSIVE::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK_NO_ARG(BM_pthread_rwlock_read);
void BM_pthread_rwlock_read::Run(int iters) {
StopBenchmarkTiming();
pthread_rwlock_t lock;
pthread_rwlock_init(&lock, NULL);
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
pthread_rwlock_rdlock(&lock);
pthread_rwlock_unlock(&lock);
}
StopBenchmarkTiming();
pthread_rwlock_destroy(&lock);
}
BENCHMARK_NO_ARG(BM_pthread_rwlock_write);
void BM_pthread_rwlock_write::Run(int iters) {
StopBenchmarkTiming();
pthread_rwlock_t lock;
pthread_rwlock_init(&lock, NULL);
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
pthread_rwlock_wrlock(&lock);
pthread_rwlock_unlock(&lock);
}
StopBenchmarkTiming();
pthread_rwlock_destroy(&lock);
}
static void* IdleThread(void*) {
return NULL;
}
BENCHMARK_NO_ARG(BM_pthread_create);
void BM_pthread_create::Run(int iters) {
StopBenchmarkTiming();
pthread_t thread;
for (int i = 0; i < iters; ++i) {
StartBenchmarkTiming();
pthread_create(&thread, NULL, IdleThread, NULL);
StopBenchmarkTiming();
pthread_join(thread, NULL);
}
}
static void* RunThread(void* arg) {
::testing::Benchmark* benchmark = reinterpret_cast<::testing::Benchmark*>(arg);
benchmark->StopBenchmarkTiming();
return NULL;
}
BENCHMARK_NO_ARG(BM_pthread_create_and_run);
void BM_pthread_create_and_run::Run(int iters) {
StopBenchmarkTiming();
pthread_t thread;
for (int i = 0; i < iters; ++i) {
StartBenchmarkTiming();
pthread_create(&thread, NULL, RunThread, this);
pthread_join(thread, NULL);
}
}
static void* ExitThread(void* arg) {
::testing::Benchmark* benchmark = reinterpret_cast<::testing::Benchmark*>(arg);
benchmark->StartBenchmarkTiming();
pthread_exit(NULL);
}
BENCHMARK_NO_ARG(BM_pthread_exit_and_join);
void BM_pthread_exit_and_join::Run(int iters) {
StopBenchmarkTiming();
pthread_t thread;
for (int i = 0; i < iters; ++i) {
pthread_create(&thread, NULL, ExitThread, this);
pthread_join(thread, NULL);
StopBenchmarkTiming();
}
}
BENCHMARK_NO_ARG(BM_pthread_key_create);
void BM_pthread_key_create::Run(int iters) {
StopBenchmarkTiming();
pthread_key_t key;
for (int i = 0; i < iters; ++i) {
StartBenchmarkTiming();
pthread_key_create(&key, NULL);
StopBenchmarkTiming();
pthread_key_delete(key);
}
}
BENCHMARK_NO_ARG(BM_pthread_key_delete);
void BM_pthread_key_delete::Run(int iters) {
StopBenchmarkTiming();
pthread_key_t key;
for (int i = 0; i < iters; ++i) {
pthread_key_create(&key, NULL);
StartBenchmarkTiming();
pthread_key_delete(key);
StopBenchmarkTiming();
}
}
BENCHMARK(BM_pthread_mutex_lock_RECURSIVE);

View File

@ -14,15 +14,11 @@
* limitations under the License.
*/
#include <pthread.h>
#include "benchmark.h"
#include <semaphore.h>
#include <stdatomic.h>
#include <stdio.h>
#include <benchmark/Benchmark.h>
BENCHMARK_NO_ARG(BM_semaphore_sem_getvalue);
void BM_semaphore_sem_getvalue::Run(int iters) {
static void BM_semaphore_sem_getvalue(int iters) {
StopBenchmarkTiming();
sem_t semaphore;
sem_init(&semaphore, 1, 1);
@ -35,9 +31,9 @@ void BM_semaphore_sem_getvalue::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_semaphore_sem_getvalue);
BENCHMARK_NO_ARG(BM_semaphore_sem_wait_sem_post);
void BM_semaphore_sem_wait_sem_post::Run(int iters) {
static void BM_semaphore_sem_wait_sem_post(int iters) {
StopBenchmarkTiming();
sem_t semaphore;
sem_init(&semaphore, 1, 1);
@ -50,94 +46,4 @@ void BM_semaphore_sem_wait_sem_post::Run(int iters) {
StopBenchmarkTiming();
}
/*
* This test reports the overhead of the underlying futex wake syscall on
* the producer. It does not report the overhead from issuing the wake to the
* point where the posted consumer thread wakes up. It suffers from
* clock_gettime syscall overhead. Lock the CPU speed for consistent results
* as we may not reach >50% cpu utilization.
*
* We will run a background thread that catches the sem_post wakeup and
* loops immediately returning back to sleep in sem_wait for the next one. This
* thread is run with policy SCHED_OTHER (normal policy), a middle policy.
*
* The primary thread will run at SCHED_IDLE (lowest priority policy) when
* monitoring the background thread to detect when it hits sem_wait sleep. It
* will do so with no clock running. Once we are ready, we will switch to
* SCHED_FIFO (highest priority policy) to time the act of running sem_post
* with the benchmark clock running. This ensures nothing else in the system
* can preempt our timed activity, including the background thread. We are
* also protected with the scheduling policy of letting a process hit a
* resource limit rather than get hit with a context switch.
*
* The background thread will start executing either on another CPU, or
* after we back down from SCHED_FIFO, but certainly not in the context of
* the timing of the sem_post.
*/
static atomic_int BM_semaphore_sem_post_running;
static void *BM_semaphore_sem_post_start_thread(void *obj) {
sem_t *semaphore = reinterpret_cast<sem_t *>(obj);
while ((BM_semaphore_sem_post_running > 0) && !sem_wait(semaphore)) {
;
}
BM_semaphore_sem_post_running = -1;
return NULL;
}
BENCHMARK_NO_ARG(BM_semaphore_sem_post);
void BM_semaphore_sem_post::Run(int iters) {
StopBenchmarkTiming();
sem_t semaphore;
sem_init(&semaphore, 0, 0);
pthread_attr_t attr;
pthread_attr_init(&attr);
BM_semaphore_sem_post_running = 1;
struct sched_param param = { 0, };
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_t pthread;
pthread_create(&pthread, &attr, BM_semaphore_sem_post_start_thread, &semaphore);
pthread_attr_destroy(&attr);
sched_setscheduler((pid_t)0, SCHED_IDLE, &param);
for (int i = 0; i < iters; ++i) {
int trys = 3, dummy = 0;
do {
if (BM_semaphore_sem_post_running < 0) {
sched_setscheduler((pid_t)0, SCHED_OTHER, &param);
fprintf(stderr, "BM_semaphore_sem_post: start_thread died unexpectedly\n");
return;
}
sched_yield();
sem_getvalue(&semaphore, &dummy);
if (dummy < 0) { // POSIX.1-2001 possibility 1
break;
}
if (dummy == 0) { // POSIX.1-2001 possibility 2
--trys;
}
} while (trys);
param.sched_priority = 1;
sched_setscheduler((pid_t)0, SCHED_FIFO, &param);
StartBenchmarkTiming();
sem_post(&semaphore);
StopBenchmarkTiming(); // Remember to subtract clock syscall overhead
param.sched_priority = 0;
sched_setscheduler((pid_t)0, SCHED_IDLE, &param);
}
sched_setscheduler((pid_t)0, SCHED_OTHER, &param);
if (BM_semaphore_sem_post_running > 0) {
BM_semaphore_sem_post_running = 0;
}
do {
sem_post(&semaphore);
sched_yield();
} while (!BM_semaphore_sem_post_running);
}
BENCHMARK(BM_semaphore_sem_wait_sem_post);

View File

@ -14,11 +14,9 @@
* limitations under the License.
*/
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include "benchmark.h"
#include <benchmark/Benchmark.h>
#include <stdio.h>
#define KB 1024
#define MB 1024*KB
@ -27,68 +25,37 @@
Arg(1)->Arg(2)->Arg(3)->Arg(4)->Arg(8)->Arg(16)->Arg(32)->Arg(64)->Arg(512)-> \
Arg(1*KB)->Arg(4*KB)->Arg(8*KB)->Arg(16*KB)->Arg(64*KB)
template <typename Fn>
void ReadWriteTest(::testing::Benchmark* benchmark, int iters, int chunk_size, Fn f, bool buffered) {
benchmark->StopBenchmarkTiming();
static void BM_stdio_fread(int iters, int chunk_size) {
StopBenchmarkTiming();
FILE* fp = fopen("/dev/zero", "rw");
__fsetlocking(fp, FSETLOCKING_BYCALLER);
char* buf = new char[chunk_size];
benchmark->StartBenchmarkTiming();
if (!buffered) {
setvbuf(fp, 0, _IONBF, 0);
}
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
f(buf, chunk_size, 1, fp);
fread(buf, chunk_size, 1, fp);
}
benchmark->StopBenchmarkTiming();
benchmark->SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(chunk_size));
StopBenchmarkTiming();
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(chunk_size));
delete[] buf;
fclose(fp);
}
BENCHMARK(BM_stdio_fread)->AT_COMMON_SIZES;
BENCHMARK_WITH_ARG(BM_stdio_fread, int)->AT_COMMON_SIZES;
void BM_stdio_fread::Run(int iters, int chunk_size) {
ReadWriteTest(this, iters, chunk_size, fread, true);
}
BENCHMARK_WITH_ARG(BM_stdio_fwrite, int)->AT_COMMON_SIZES;
void BM_stdio_fwrite::Run(int iters, int chunk_size) {
ReadWriteTest(this, iters, chunk_size, fwrite, true);
}
static void BM_stdio_fwrite(int iters, int chunk_size) {
StopBenchmarkTiming();
FILE* fp = fopen("/dev/zero", "rw");
char* buf = new char[chunk_size];
StartBenchmarkTiming();
BENCHMARK_WITH_ARG(BM_stdio_fread_unbuffered, int)->AT_COMMON_SIZES;
void BM_stdio_fread_unbuffered::Run(int iters, int chunk_size) {
ReadWriteTest(this, iters, chunk_size, fread, false);
}
BENCHMARK_WITH_ARG(BM_stdio_fwrite_unbuffered, int)->AT_COMMON_SIZES;
void BM_stdio_fwrite_unbuffered::Run(int iters, int chunk_size) {
ReadWriteTest(this, iters, chunk_size, fwrite, false);
}
static void FopenFgetsFclose(int iters, bool no_locking) {
char buf[1024];
for (int i = 0; i < iters; ++i) {
FILE* fp = fopen("/proc/version", "re");
if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
if (fgets(buf, sizeof(buf), fp) == nullptr) abort();
fclose(fp);
fwrite(buf, chunk_size, 1, fp);
}
}
BENCHMARK_NO_ARG(BM_stdio_fopen_fgets_fclose_locking);
void BM_stdio_fopen_fgets_fclose_locking::Run(int iters) {
StartBenchmarkTiming();
FopenFgetsFclose(iters, false);
StopBenchmarkTiming();
}
BENCHMARK_NO_ARG(BM_stdio_fopen_fgets_fclose_no_locking);
void BM_stdio_fopen_fgets_fclose_no_locking::Run(int iters) {
StartBenchmarkTiming();
FopenFgetsFclose(iters, true);
StopBenchmarkTiming();
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(chunk_size));
delete[] buf;
fclose(fp);
}
BENCHMARK(BM_stdio_fwrite)->AT_COMMON_SIZES;

View File

@ -14,10 +14,9 @@
* limitations under the License.
*/
#include <stdint.h>
#include <string.h>
#include "benchmark.h"
#include <benchmark/Benchmark.h>
#include <string.h>
#define KB 1024
#define MB 1024*KB
@ -27,8 +26,7 @@
// TODO: test unaligned operation too? (currently everything will be 8-byte aligned by malloc.)
BENCHMARK_WITH_ARG(BM_string_memcmp, int)->AT_COMMON_SIZES;
void BM_string_memcmp::Run(int iters, int nbytes) {
static void BM_string_memcmp(int iters, int nbytes) {
StopBenchmarkTiming();
char* src = new char[nbytes]; char* dst = new char[nbytes];
memset(src, 'x', nbytes);
@ -41,13 +39,13 @@ void BM_string_memcmp::Run(int iters, int nbytes) {
}
StopBenchmarkTiming();
SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
delete[] src;
delete[] dst;
}
BENCHMARK(BM_string_memcmp)->AT_COMMON_SIZES;
BENCHMARK_WITH_ARG(BM_string_memcpy, int)->AT_COMMON_SIZES;
void BM_string_memcpy::Run(int iters, int nbytes) {
static void BM_string_memcpy(int iters, int nbytes) {
StopBenchmarkTiming();
char* src = new char[nbytes]; char* dst = new char[nbytes];
memset(src, 'x', nbytes);
@ -58,13 +56,13 @@ void BM_string_memcpy::Run(int iters, int nbytes) {
}
StopBenchmarkTiming();
SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
delete[] src;
delete[] dst;
}
BENCHMARK(BM_string_memcpy)->AT_COMMON_SIZES;
BENCHMARK_WITH_ARG(BM_string_memmove, int)->AT_COMMON_SIZES;
void BM_string_memmove::Run(int iters, int nbytes) {
static void BM_string_memmove(int iters, int nbytes) {
StopBenchmarkTiming();
char* buf = new char[nbytes + 64];
memset(buf, 'x', nbytes + 64);
@ -75,12 +73,12 @@ void BM_string_memmove::Run(int iters, int nbytes) {
}
StopBenchmarkTiming();
SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
delete[] buf;
}
BENCHMARK(BM_string_memmove)->AT_COMMON_SIZES;
BENCHMARK_WITH_ARG(BM_string_memset, int)->AT_COMMON_SIZES;
void BM_string_memset::Run(int iters, int nbytes) {
static void BM_string_memset(int iters, int nbytes) {
StopBenchmarkTiming();
char* dst = new char[nbytes];
StartBenchmarkTiming();
@ -90,12 +88,12 @@ void BM_string_memset::Run(int iters, int nbytes) {
}
StopBenchmarkTiming();
SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
delete[] dst;
}
BENCHMARK(BM_string_memset)->AT_COMMON_SIZES;
BENCHMARK_WITH_ARG(BM_string_strlen, int)->AT_COMMON_SIZES;
void BM_string_strlen::Run(int iters, int nbytes) {
static void BM_string_strlen(int iters, int nbytes) {
StopBenchmarkTiming();
char* s = new char[nbytes];
memset(s, 'x', nbytes);
@ -108,6 +106,7 @@ void BM_string_strlen::Run(int iters, int nbytes) {
}
StopBenchmarkTiming();
SetBenchmarkBytesProcessed(uint64_t(iters) * uint64_t(nbytes));
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
delete[] s;
}
BENCHMARK(BM_string_strlen)->AT_COMMON_SIZES;

View File

@ -14,15 +14,12 @@
* limitations under the License.
*/
#include "benchmark.h"
#include <sys/syscall.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <benchmark/Benchmark.h>
BENCHMARK_NO_ARG(BM_time_clock_gettime);
void BM_time_clock_gettime::Run(int iters) {
static void BM_time_clock_gettime(int iters) {
StartBenchmarkTiming();
timespec t;
@ -32,9 +29,9 @@ void BM_time_clock_gettime::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_time_clock_gettime);
BENCHMARK_NO_ARG(BM_time_clock_gettime_syscall);
void BM_time_clock_gettime_syscall::Run(int iters) {
static void BM_time_clock_gettime_syscall(int iters) {
StartBenchmarkTiming();
timespec t;
@ -44,9 +41,9 @@ void BM_time_clock_gettime_syscall::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_time_clock_gettime_syscall);
BENCHMARK_NO_ARG(BM_time_gettimeofday);
void BM_time_gettimeofday::Run(int iters) {
static void BM_time_gettimeofday(int iters) {
StartBenchmarkTiming();
timeval tv;
@ -56,9 +53,9 @@ void BM_time_gettimeofday::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_time_gettimeofday);
BENCHMARK_NO_ARG(BM_time_gettimeofday_syscall);
void BM_time_gettimeofday_syscall::Run(int iters) {
static void BM_time_gettimeofday_syscall(int iters) {
StartBenchmarkTiming();
timeval tv;
@ -68,9 +65,9 @@ void BM_time_gettimeofday_syscall::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_time_gettimeofday_syscall);
BENCHMARK_NO_ARG(BM_time_time);
void BM_time_time::Run(int iters) {
static void BM_time_time(int iters) {
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
@ -79,3 +76,4 @@ void BM_time_time::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_time_time);

View File

@ -14,13 +14,12 @@
* limitations under the License.
*/
#include "benchmark.h"
#include <sys/syscall.h>
#include <unistd.h>
#include <benchmark/Benchmark.h>
BENCHMARK_NO_ARG(BM_unistd_getpid);
void BM_unistd_getpid::Run(int iters) {
static void BM_unistd_getpid(int iters) {
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
@ -29,9 +28,9 @@ void BM_unistd_getpid::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_unistd_getpid);
BENCHMARK_NO_ARG(BM_unistd_getpid_syscall);
void BM_unistd_getpid_syscall::Run(int iters) {
static void BM_unistd_getpid_syscall(int iters) {
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
@ -40,14 +39,12 @@ void BM_unistd_getpid_syscall::Run(int iters) {
StopBenchmarkTiming();
}
#if defined(__BIONIC__)
BENCHMARK(BM_unistd_getpid_syscall);
// Stop GCC optimizing out our pure function.
/* Must not be static! */ pid_t (*gettid_fp)() = gettid;
BENCHMARK_NO_ARG(BM_unistd_gettid);
void BM_unistd_gettid::Run(int iters) {
static void BM_unistd_gettid(int iters) {
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
@ -56,11 +53,9 @@ void BM_unistd_gettid::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_unistd_gettid);
#endif
BENCHMARK_NO_ARG(BM_unistd_gettid_syscall);
void BM_unistd_gettid_syscall::Run(int iters) {
static void BM_unistd_gettid_syscall(int iters) {
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
@ -69,3 +64,4 @@ void BM_unistd_gettid_syscall::Run(int iters) {
StopBenchmarkTiming();
}
BENCHMARK(BM_unistd_gettid_syscall);

View File

@ -1,80 +0,0 @@
/*
* Copyright (C) 2012 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.
*/
#include "utils.h"
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string>
#include <android-base/stringprintf.h>
int Round(int n) {
int base = 1;
while (base*10 < n) {
base *= 10;
}
if (n < 2*base) {
return 2*base;
}
if (n < 5*base) {
return 5*base;
}
return 10*base;
}
// Similar to the code in art, but supporting both binary and decimal prefixes.
std::string PrettyInt(long value, size_t base) {
if (base != 2 && base != 10) abort();
uint64_t count = static_cast<uint64_t>(value);
bool negative_number = false;
if (value < 0) {
negative_number = true;
count = static_cast<uint64_t>(-value);
}
// The byte thresholds at which we display amounts. A count is displayed
// in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1].
static const uint64_t kUnitThresholds2[] = {
1024*1024*1024 /* Gi */, 2*1024*1024 /* Mi */, 3*1024 /* Ki */, 0,
};
static const uint64_t kUnitThresholds10[] = {
1000*1000*1000 /* G */, 2*1000*1000 /* M */, 3*1000 /* k */, 0,
};
static const uint64_t kAmountPerUnit2[] = { 1024*1024*1024, 1024*1024, 1024, 1 };
static const uint64_t kAmountPerUnit10[] = { 1000*1000*1000, 1000*1000, 1000, 1 };
static const char* const kUnitStrings2[] = { "Gi", "Mi", "Ki", "" };
static const char* const kUnitStrings10[] = { "G", "M", "k", "" };
// Which set are we using?
const uint64_t* kUnitThresholds = ((base == 2) ? kUnitThresholds2 : kUnitThresholds10);
const uint64_t* kAmountPerUnit = ((base == 2) ? kAmountPerUnit2 : kAmountPerUnit10);
const char* const* kUnitStrings = ((base == 2) ? kUnitStrings2 : kUnitStrings10);
size_t i = 0;
for (; kUnitThresholds[i] != 0; ++i) {
if (count >= kUnitThresholds[i]) {
break;
}
}
return android::base::StringPrintf("%s%" PRId64 "%s",
negative_number ? "-" : "",
count / kAmountPerUnit[i], kUnitStrings[i]);
}

View File

@ -1,44 +0,0 @@
#
# Copyright (C) 2014 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.
#
# Include once
ifneq ($(bionic_run_on_host_mk_included),true)
bionic_run_on_host_mk_included:=true
ifneq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),arm mips x86))
LINKER = linker64
else
LINKER = linker
endif
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86 x86_64))
# gtest needs ANDROID_DATA/local/tmp for death test output.
# Make sure to create ANDROID_DATA/local/tmp if doesn't exist.
# bionic itself should always work relative to ANDROID_DATA or ANDROID_ROOT.
bionic-prepare-run-on-host: $(TARGET_OUT_EXECUTABLES)/$(LINKER) $(TARGET_OUT)/etc/hosts $(TARGET_OUT_EXECUTABLES)/sh
if [ ! -d /system ]; then \
echo "Attempting to create /system"; \
sudo mkdir -p -m 0777 /system; \
fi
mkdir -p $(TARGET_OUT_DATA)/local/tmp
ln -fs `realpath $(TARGET_OUT)/bin` /system/
ln -fs `realpath $(TARGET_OUT)/etc` /system/
ln -fs `realpath $(TARGET_OUT)/lib` /system/
if [ -d "$(TARGET_OUT)/lib64" ]; then \
ln -fs `realpath $(TARGET_OUT)/lib64` /system/; \
fi
endif
endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -307,6 +307,50 @@ SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (C) 2008-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.
-------------------------------------------------------------------
Copyright (C) 2009 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.
-------------------------------------------------------------------
Copyright (C) 2009 The Android Open Source Project
All rights reserved.
@ -410,6 +454,22 @@ Android adaptation and tweak by Jim Huang <jserv@0xlab.org>.
-------------------------------------------------------------------
Copyright (C) 2011 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.
-------------------------------------------------------------------
Copyright (C) 2011 The Android Open Source Project
All rights reserved.
@ -628,50 +688,6 @@ SUCH DAMAGE.
-------------------------------------------------------------------
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.
-------------------------------------------------------------------
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.
-------------------------------------------------------------------
Copyright (c) 1980, 1983, 1988, 1993
The Regents of the University of California. All rights reserved.
@ -1663,6 +1679,35 @@ SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 1990 Regents of the University of California.
All rights reserved.
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.
-------------------------------------------------------------------
Copyright (c) 1990 The Regents of the University of California.
All rights reserved.
@ -2465,6 +2510,35 @@ SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 1993
The Regents of the University of California. All rights reserved.
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.
-------------------------------------------------------------------
Copyright (c) 1993
The Regents of the University of California. All rights reserved.
@ -2494,6 +2568,33 @@ SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 1993 Christopher G. Demetriou
All rights reserved.
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. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-------------------------------------------------------------------
Copyright (c) 1993 Martin Birgmeier
All rights reserved.
@ -2534,6 +2635,33 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 1995, 1996 Carnegie-Mellon University.
All rights reserved.
Author: Chris G. Demetriou
Permission to use, copy, modify and distribute this software and
its documentation is hereby granted, provided that both the copyright
notice and this permission notice appear in all copies of the
software, derivative works or modified versions, and any portions
thereof, and that both notices appear in supporting documentation.
CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
Carnegie Mellon requests users of this software to return to
Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
School of Computer Science
Carnegie Mellon University
Pittsburgh PA 15213-3890
any improvements or extensions that they make and grant Carnegie the
rights to redistribute these changes.
-------------------------------------------------------------------
Copyright (c) 1996 by Internet Software Consortium.
Permission to use, copy, modify, and distribute this software for any
@ -2586,6 +2714,63 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-------------------------------------------------------------------
Copyright (c) 1996-2004 Per Fogelstrom, Opsycon AB
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.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-------------------------------------------------------------------
Copyright (c) 1997 Mark Brinicombe
All rights reserved.
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. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by Mark Brinicombe
4. 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 AUTHOR 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 AUTHOR 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.
-------------------------------------------------------------------
Copyright (c) 1997 Mark Brinicombe
Copyright (c) 2010 Android Open Source Project.
All rights reserved.
@ -2946,6 +3131,38 @@ SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 1999 Kungliga Tekniska Högskolan
(Royal Institute of Technology, Stockholm, Sweden).
All rights reserved.
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 KTH 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 KTH AND ITS 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 KTH OR ITS 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
-------------------------------------------------------------------
Copyright (c) 2000 Ben Harris.
Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
All rights reserved.
@ -3209,6 +3426,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 2002 Opsycon AB (www.opsycon.se / www.opsycon.com)
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 Opsycon AB 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 AUTHOR ``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 AUTHOR 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.
-------------------------------------------------------------------
Copyright (c) 2002 The NetBSD Foundation, Inc.
All rights reserved.
@ -3752,22 +3997,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-------------------------------------------------------------------
Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-------------------------------------------------------------------
Copyright (c) 2007-2008 Michael G Schwern
This software originally derived from Paul Sheer's pivotal_gmtime_r.c.
@ -3857,22 +4086,6 @@ SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-------------------------------------------------------------------
Copyright (c) 2008 Todd C. Miller <millert@openbsd.org>
Permission to use, copy, modify, and distribute this software for any
@ -3905,6 +4118,35 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-------------------------------------------------------------------
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.
-------------------------------------------------------------------
Copyright (c) 2009 David Schultz <das@FreeBSD.org>
All rights reserved.
@ -4180,39 +4422,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-------------------------------------------------------------------
Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
Copyright (c) 2009 Ted Unangst
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-------------------------------------------------------------------
Copyright (c) 2011 The Android Open Source Project
Copyright (c) 2008 ARM Ltd
All rights reserved.
@ -4386,64 +4595,6 @@ Copyright (c) 2012, Linaro Limited
-------------------------------------------------------------------
Copyright (c) 2012-2015
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.
-------------------------------------------------------------------
Copyright (c) 2013
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.
-------------------------------------------------------------------
Copyright (c) 2013 ARM Ltd
All rights reserved.
@ -4488,61 +4639,35 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-------------------------------------------------------------------
Copyright (c) 2013 The NetBSD Foundation, Inc.
All rights reserved.
Copyright (c) 2013, Linaro Limited
All rights reserved.
This code is derived from software contributed to The NetBSD Foundation
by Christos Zoulas.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
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.
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
* 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 Linaro Limited nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
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.
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
HOLDER 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.
-------------------------------------------------------------------
@ -4728,20 +4853,9 @@ SUCH DAMAGE.
-------------------------------------------------------------------
Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
Copyright 2008 Damien Miller <djm@openbsd.org>
Copyright 2000 David E. O'Brien, John D. Polstra.
All rights reserved.
Theo de Raadt <deraadt@openbsd.org> came up with the idea of using
such a mathematical system to generate more random (yet non-repeating)
ids to solve the resolver/named problem. But Niels designed the
actual system based on the constraints.
Later modified by Damien Miller to wrap the LCG output in a 15-bit
permutation generator based on a Luby-Rackoff block cipher. This
ensures the output is non-repeating and preserves the MSB twiddle
trick, but makes it more resistant to LCG prediction.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

View File

@ -77,6 +77,7 @@ int prlimit64(pid_t, int, struct rlimit64*, const struct rlimit64*) arm,mips,x8
int setgroups:setgroups32(int, const gid_t*) arm,x86
int setgroups:setgroups(int, const gid_t*) arm64,mips,mips64,x86_64
int setpgid(pid_t, pid_t) all
pid_t vfork(void) arm
int setregid:setregid32(gid_t, gid_t) arm,x86
int setregid:setregid(gid_t, gid_t) arm64,mips,mips64,x86_64
int chroot(const char*) all
@ -94,23 +95,13 @@ ssize_t pread64(int, void*, size_t, off64_t) arm,mips,x86
ssize_t pread64|pread(int, void*, size_t, off_t) arm64,mips64,x86_64
ssize_t pwrite64(int, void*, size_t, off64_t) arm,mips,x86
ssize_t pwrite64|pwrite(int, void*, size_t, off_t) arm64,mips64,x86_64
# On LP32, preadv/pwritev don't use off64_t --- they use pairs of 32-bit
# arguments to avoid problems on architectures like ARM where 64-bit arguments
# must be in a register pair starting with an even-numbered register.
# See linux/fs/read_write.c and https://lwn.net/Articles/311630/.
ssize_t __preadv64:preadv(int, const struct iovec*, int, long, long) arm,mips,x86
ssize_t preadv|preadv64(int, const struct iovec*, int, off_t) arm64,mips64,x86_64
ssize_t __pwritev64:pwritev(int, const struct iovec*, int, long, long) arm,mips,x86
ssize_t pwritev|pwritev64(int, const struct iovec*, int, off_t) arm64,mips64,x86_64
int ___close:close(int) all
int close(int) all
pid_t __getpid:getpid() all
int munmap(void*, size_t) all
void* ___mremap:mremap(void*, size_t, size_t, int, void*) all
void* mremap(void*, size_t, size_t, unsigned long) all
int msync(const void*, size_t, int) all
int mprotect(const void*, size_t, int) all
int madvise(void*, size_t, int) all
int madvise(const void*, size_t, int) all
int mlock(const void* addr, size_t len) all
int munlock(const void* addr, size_t len) all
int mlockall(int flags) all
@ -122,7 +113,7 @@ int writev(int, const struct iovec*, int) all
int __fcntl64:fcntl64(int, int, void*) arm,mips,x86
int fcntl(int, int, void*) arm64,mips64,x86_64
int flock(int, int) all
int ___fchmod:fchmod(int, mode_t) all
int fchmod(int, mode_t) all
int dup(int) all
int pipe2(int*, int) all
int dup3(int, int, int) all
@ -131,19 +122,19 @@ 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
ssize_t ___flistxattr:flistxattr(int, char*, 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
int __getdents64:getdents64(unsigned int, struct dirent*, unsigned int) arm,arm64,mips,mips64,x86,x86_64
int __openat:openat(int, const char*, int, mode_t) all
int ___faccessat:faccessat(int, const char*, int) all
int ___fchmodat:fchmodat(int, const char*, mode_t) all
int faccessat(int, const char*, int, int) all
int fchmodat(int, const char*, mode_t, int) all
int fchownat(int, const char*, uid_t, gid_t, int) all
int fstatat64|fstatat:fstatat64(int, const char*, struct stat*, int) arm,mips,x86
int fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int) arm64,x86_64
int fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int) arm64,mips64,x86_64
int linkat(int, const char*, int, const char*, int) all
int mkdirat(int, const char*, mode_t) all
int mknodat(int, const char*, mode_t, dev_t) all
@ -160,6 +151,7 @@ int utimensat(int, const char*, const struct timespec times[2], int) all
off_t lseek(int, off_t, int) arm,mips,x86
int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) arm,mips,x86
off_t lseek|lseek64(int, off_t, int) arm64,mips64,x86_64
int ftruncate(int, off_t) arm,mips,x86
int ftruncate64(int, off64_t) arm,mips,x86
int ftruncate|ftruncate64(int, off_t) arm64,mips64,x86_64
ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) arm,mips,x86
@ -182,12 +174,12 @@ int __fadvise64:fadvise64_64(int, off64_t, off64_t, int) x86
int __fadvise64:fadvise64(int, off64_t, off64_t, int) arm64,mips,mips64,x86_64
int __fstatfs64:fstatfs64(int, size_t, struct statfs*) arm,mips,x86
int __fstatfs:fstatfs(int, struct statfs*) arm64,mips64,x86_64
int fstatfs64|fstatfs:fstatfs(int, struct statfs*) arm64,mips64,x86_64
int __statfs64:statfs64(const char*, size_t, struct statfs*) arm,mips,x86
int __statfs:statfs(const char*, struct statfs*) arm64,mips64,x86_64
int statfs64|statfs:statfs(const char*, struct statfs*) arm64,mips64,x86_64
int fstat64|fstat:fstat64(int, struct stat*) arm,mips,x86
int fstat64|fstat:fstat(int, struct stat*) arm64,x86_64
int fstat64|fstat:fstat(int, struct stat*) arm64,mips64,x86_64
# file system
int chdir(const char*) all
@ -210,9 +202,9 @@ int swapoff(const char*) all
int settimeofday(const struct timeval*, const struct timezone*) all
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_settime(clockid_t clk_id, const struct timespec* tp) all
int clock_getres(clockid_t clk_id, struct timespec* res) all
int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec* req, struct timespec* rem) 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
@ -231,7 +223,6 @@ int __rt_sigpending:rt_sigpending(sigset_t*, size_t) all
int __rt_sigprocmask:rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t) all
int __rt_sigsuspend:rt_sigsuspend(const sigset_t*, size_t) all
int __rt_sigtimedwait:rt_sigtimedwait(const sigset_t*, struct siginfo_t*, struct timespec_t*, size_t) all
int ___rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*) all
int __signalfd4:signalfd4(int, const sigset_t*, size_t, int) all
# sockets
@ -317,16 +308,11 @@ 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
int setfsuid(uid_t) all
int sethostname(const char*, size_t) all
pid_t wait4(pid_t, int*, int, struct rusage*) all
int __waitid:waitid(int, pid_t, struct siginfo_t*, int, void*) all
@ -335,14 +321,14 @@ int __set_tls:__ARM_NR_set_tls(void*) arm
int cacheflush:__ARM_NR_cacheflush(long start, long end, long flags) arm
# MIPS-specific
int _flush_cache:cacheflush(char* addr, const int nbytes, const int op) mips
int _flush_cache:cacheflush(char* addr, const int nbytes, const int op) mips,mips64
int __set_tls:set_thread_area(void*) mips,mips64
# x86-specific
int __set_thread_area:set_thread_area(void*) x86
# vdso stuff.
int clock_gettime(clockid_t, timespec*) arm,mips,mips64
int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86,x86_64
int gettimeofday(timeval*, timezone*) arm,mips,mips64
int __gettimeofday:gettimeofday(timeval*, timezone*) arm64,x86,x86_64
int clock_gettime(clockid_t, timespec*) arm,mips,mips64,x86
int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86_64
int gettimeofday(timeval*, timezone*) arm,mips,mips64,x86
int __gettimeofday:gettimeofday(timeval*, timezone*) arm64,x86_64

View File

@ -1,19 +1,52 @@
# 32-bit arm.
#
# Various kinds of LP32 cruft.
#
libc_bionic_src_files_arm += \
arch-arm/generic/bionic/memcmp.S \
arch-arm/generic/bionic/memcpy.S \
arch-arm/generic/bionic/memset.S \
arch-arm/generic/bionic/strcmp.S \
arch-arm/generic/bionic/strcpy.S \
arch-arm/generic/bionic/strlen.c \
bionic/mmap.cpp \
libc_bionic_src_files_exclude_arm += \
bionic/__memcpy_chk.cpp \
bionic/__memset_chk.cpp \
libc_common_src_files_arm += \
bionic/legacy_32_bit_support.cpp \
bionic/ndk_cruft.cpp \
bionic/time64.c \
libc_openbsd_src_files_exclude_arm += \
upstream-openbsd/lib/libc/string/strcpy.c \
libc_netbsd_src_files_arm += \
upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
libc_openbsd_src_files_arm += \
upstream-openbsd/lib/libc/stdio/putw.c \
#
# Default implementations of functions that are commonly optimized.
#
libc_bionic_src_files_arm += \
bionic/memchr.c \
bionic/memrchr.c \
bionic/strchr.cpp \
bionic/strnlen.c \
bionic/strrchr.cpp \
libc_freebsd_src_files_arm += \
upstream-freebsd/lib/libc/string/wcscat.c \
upstream-freebsd/lib/libc/string/wcschr.c \
upstream-freebsd/lib/libc/string/wcscmp.c \
upstream-freebsd/lib/libc/string/wcscpy.c \
upstream-freebsd/lib/libc/string/wcslen.c \
upstream-freebsd/lib/libc/string/wcsrchr.c \
upstream-freebsd/lib/libc/string/wmemcmp.c \
upstream-freebsd/lib/libc/string/wmemmove.c \
libc_openbsd_src_files_arm += \
upstream-openbsd/lib/libc/string/bcopy.c \
upstream-openbsd/lib/libc/string/stpncpy.c \
upstream-openbsd/lib/libc/string/strlcat.c \
upstream-openbsd/lib/libc/string/strlcpy.c \
upstream-openbsd/lib/libc/string/strncat.c \
upstream-openbsd/lib/libc/string/strncmp.c \
upstream-openbsd/lib/libc/string/strncpy.c \
#
# Inherently architecture-specific code.
@ -25,11 +58,12 @@ 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/popcount_tab.c \
arch-arm/bionic/memcmp.S \
arch-arm/bionic/__restore.S \
arch-arm/bionic/_setjmp.S \
arch-arm/bionic/setjmp.S \
arch-arm/bionic/sigsetjmp.S \
arch-arm/bionic/syscall.S \
arch-arm/bionic/vfork.S \
libc_arch_static_src_files_arm := arch-arm/bionic/exidx_static.c
libc_arch_dynamic_src_files_arm := arch-arm/bionic/exidx_dynamic.c
@ -38,7 +72,6 @@ libc_arch_dynamic_src_files_arm := arch-arm/bionic/exidx_dynamic.c
ifeq ($(strip $(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT)),)
$(warning TARGET_$(my_2nd_arch_prefix)ARCH is arm, but TARGET_$(my_2nd_arch_prefix)CPU_VARIANT is not defined)
endif
ifneq ($(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT),generic)
cpu_variant_mk := $(LOCAL_PATH)/arch-arm/$(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT)/$(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT).mk
ifeq ($(wildcard $(cpu_variant_mk)),)
$(error "TARGET_$(my_2nd_arch_prefix)CPU_VARIANT not set or set to an unknown value. Possible values are cortex-a7, cortex-a8, cortex-a9, cortex-a15, krait, denver. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
@ -47,7 +80,6 @@ include $(cpu_variant_mk)
libc_common_additional_dependencies += $(cpu_variant_mk)
cpu_variant_mk :=
endif
libc_crt_target_cflags_arm := \

View File

@ -39,9 +39,6 @@
extern int __cxa_atexit(void (*)(void*), void*, void*);
// All of these are weak symbols to avoid multiple definition errors when
// linking with libstdc++-v3 or compiler-rt.
/* The "C++ ABI for ARM" document states that static C++ constructors,
* which are called from the .init_array, should manually call
* __aeabi_atexit() to register static destructors explicitly.
@ -50,63 +47,35 @@ extern int __cxa_atexit(void (*)(void*), void*, void*);
* variable from the shared object that contains the constructor/destructor
*/
// Make this a weak symbol to avoid a multiple definition error when linking with libstdc++-v3.
int __attribute__((weak))
__aeabi_atexit_impl(void *object, void (*destructor) (void *), void *dso_handle) {
return __cxa_atexit(destructor, object, dso_handle);
}
int __attribute__((weak))
__aeabi_atexit_impl2(void *object, void (*destructor) (void *), void *dso_handle) {
__aeabi_atexit(void *object, void (*destructor) (void *), void *dso_handle) {
return __cxa_atexit(destructor, object, dso_handle);
}
void __attribute__((weak)) __aeabi_memcpy8_impl(void *dest, const void *src, size_t n) {
void __aeabi_memcpy8(void *dest, const void *src, size_t n) {
memcpy(dest, src, n);
}
void __attribute__((weak)) __aeabi_memcpy4_impl(void *dest, const void *src, size_t n) {
void __aeabi_memcpy4(void *dest, const void *src, size_t n) {
memcpy(dest, src, n);
}
void __attribute__((weak)) __aeabi_memcpy_impl(void *dest, const void *src, size_t n) {
memcpy(dest, src, n);
}
void __attribute__((weak)) __aeabi_memcpy8_impl2(void *dest, const void *src, size_t n) {
memcpy(dest, src, n);
}
void __attribute__((weak)) __aeabi_memcpy4_impl2(void *dest, const void *src, size_t n) {
memcpy(dest, src, n);
}
void __attribute__((weak)) __aeabi_memcpy_impl2(void *dest, const void *src, size_t n) {
void __aeabi_memcpy(void *dest, const void *src, size_t n) {
memcpy(dest, src, n);
}
void __attribute__((weak)) __aeabi_memmove8_impl(void *dest, const void *src, size_t n) {
void __aeabi_memmove8(void *dest, const void *src, size_t n) {
memmove(dest, src, n);
}
void __attribute__((weak)) __aeabi_memmove4_impl(void *dest, const void *src, size_t n) {
void __aeabi_memmove4(void *dest, const void *src, size_t n) {
memmove(dest, src, n);
}
void __attribute__((weak)) __aeabi_memmove_impl(void *dest, const void *src, size_t n) {
memmove(dest, src, n);
}
void __attribute__((weak)) __aeabi_memmove8_impl2(void *dest, const void *src, size_t n) {
memmove(dest, src, n);
}
void __attribute__((weak)) __aeabi_memmove4_impl2(void *dest, const void *src, size_t n) {
memmove(dest, src, n);
}
void __attribute__((weak)) __aeabi_memmove_impl2(void *dest, const void *src, size_t n) {
void __aeabi_memmove(void *dest, const void *src, size_t n) {
memmove(dest, src, n);
}
@ -115,71 +84,27 @@ void __attribute__((weak)) __aeabi_memmove_impl2(void *dest, const void *src, si
* This allows __aeabi_memclr to tail-call __aeabi_memset
*/
void __attribute__((weak)) __aeabi_memset8_impl(void *dest, size_t n, int c) {
void __aeabi_memset8(void *dest, size_t n, int c) {
memset(dest, c, n);
}
void __attribute__((weak)) __aeabi_memset4_impl(void *dest, size_t n, int c) {
void __aeabi_memset4(void *dest, size_t n, int c) {
memset(dest, c, n);
}
void __attribute__((weak)) __aeabi_memset_impl(void *dest, size_t n, int c) {
memset(dest, c, n);
}
void __attribute__((weak)) __aeabi_memset8_impl2(void *dest, size_t n, int c) {
memset(dest, c, n);
}
void __attribute__((weak)) __aeabi_memset4_impl2(void *dest, size_t n, int c) {
memset(dest, c, n);
}
void __attribute__((weak)) __aeabi_memset_impl2(void *dest, size_t n, int c) {
void __aeabi_memset(void *dest, size_t n, int c) {
memset(dest, c, n);
}
void __attribute__((weak)) __aeabi_memclr8_impl(void *dest, size_t n) {
__aeabi_memset8_impl(dest, n, 0);
void __aeabi_memclr8(void *dest, size_t n) {
__aeabi_memset8(dest, n, 0);
}
void __attribute__((weak)) __aeabi_memclr4_impl(void *dest, size_t n) {
__aeabi_memset4_impl(dest, n, 0);
void __aeabi_memclr4(void *dest, size_t n) {
__aeabi_memset4(dest, n, 0);
}
void __attribute__((weak)) __aeabi_memclr_impl(void *dest, size_t n) {
__aeabi_memset_impl(dest, n, 0);
void __aeabi_memclr(void *dest, size_t n) {
__aeabi_memset(dest, n, 0);
}
void __attribute__((weak)) __aeabi_memclr8_impl2(void *dest, size_t n) {
__aeabi_memset8_impl(dest, n, 0);
}
void __attribute__((weak)) __aeabi_memclr4_impl2(void *dest, size_t n) {
__aeabi_memset4_impl(dest, n, 0);
}
void __attribute__((weak)) __aeabi_memclr_impl2(void *dest, size_t n) {
__aeabi_memset_impl(dest, n, 0);
}
#define __AEABI_SYMVERS(fn_name) \
__asm__(".symver " #fn_name "_impl, " #fn_name "@@LIBC_N"); \
__asm__(".symver " #fn_name "_impl2, " #fn_name "@LIBC_PRIVATE")
__AEABI_SYMVERS(__aeabi_atexit);
__AEABI_SYMVERS(__aeabi_memcpy8);
__AEABI_SYMVERS(__aeabi_memcpy4);
__AEABI_SYMVERS(__aeabi_memcpy);
__AEABI_SYMVERS(__aeabi_memmove8);
__AEABI_SYMVERS(__aeabi_memmove4);
__AEABI_SYMVERS(__aeabi_memmove);
__AEABI_SYMVERS(__aeabi_memset8);
__AEABI_SYMVERS(__aeabi_memset4);
__AEABI_SYMVERS(__aeabi_memset);
__AEABI_SYMVERS(__aeabi_memclr8);
__AEABI_SYMVERS(__aeabi_memclr4);
__AEABI_SYMVERS(__aeabi_memclr);
#undef __AEABI_SYMVERS

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (C) 2008-2010 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -42,14 +42,13 @@ ENTRY(__bionic_clone)
# load extra parameters
ldmfd ip, {r4, r5, r6}
# Push 'fn' and 'arg' onto the child stack.
stmdb r1!, {r5, r6}
# store 'fn' and 'arg' to the child stack
str r5, [r1, #-4]
str r6, [r1, #-8]
# Make the system call.
# System call
ldr r7, =__NR_clone
swi #0
# Are we the child?
movs r0, r0
beq 1f
@ -63,8 +62,8 @@ ENTRY(__bionic_clone)
1: # The child.
# Setting lr to 0 will make the unwinder stop at __start_thread
mov lr, #0
# Call __start_thread with the 'fn' and 'arg' we stored on the child stack.
pop {r0, r1}
ldr r0, [sp, #-4]
ldr r1, [sp, #-8]
b __start_thread
END(__bionic_clone)
.hidden __bionic_clone

View File

@ -34,9 +34,7 @@
// __restore_rt (but covered by the .fnstart/.fnend) so that although they're
// not inside the functions from objdump's point of view, an unwinder that
// blindly looks at the previous instruction (but is then smart enough to check
// the unwind information to find out where it landed) gets the right answer.
// Make sure not to have both DWARF and ARM unwind information, so only
// use the ARM unwind information.
// the DWARF information to find out where it landed) gets the right answer.
// We need to place .fnstart ourselves (but we may as well keep the free .fnend).
#undef __bionic_asm_custom_entry
@ -46,18 +44,18 @@
.save {r0-r15}
.pad #32
nop
ENTRY_PRIVATE_NO_DWARF(__restore)
ENTRY_PRIVATE(__restore)
// This function must have exactly this instruction sequence.
mov r7, #__NR_sigreturn
swi #0
END_NO_DWARF(__restore)
END(__restore)
.fnstart
.save {r0-r15}
.pad #160
nop
ENTRY_PRIVATE_NO_DWARF(__restore_rt)
ENTRY_PRIVATE(__restore_rt)
// This function must have exactly this instruction sequence.
mov r7, #__NR_rt_sigreturn
swi #0
END_NO_DWARF(__restore_rt)
END(__restore_rt)

View File

@ -0,0 +1,113 @@
/* $OpenBSD: _setjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $ */
/* $NetBSD: _setjmp.S,v 1.5 2003/04/05 23:08:51 bjh21 Exp $ */
/*
* Copyright (c) 1997 Mark Brinicombe
* Copyright (c) 2010 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:
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Mark Brinicombe
* 4. 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 AUTHOR 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 AUTHOR 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 <private/bionic_asm.h>
#include <machine/setjmp.h>
#include <machine/cpu-features.h>
/*
* C library -- _setjmp, _longjmp
*
* _longjmp(a,v)
* will generate a "return(v)" from the last call to
* _setjmp(a)
* by restoring registers from the stack.
* The previous signal state is NOT restored.
*
* Note: r0 is the return value
* r1-r3 are scratch registers in functions
*/
ENTRY(_setjmp)
ldr r1, .L_setjmp_magic
str r1, [r0, #(_JB_MAGIC * 4)]
/* Store core registers */
add r1, r0, #(_JB_CORE_BASE * 4)
stmia r1, {r4-r14}
#ifdef __ARM_HAVE_VFP
/* Store floating-point registers */
add r1, r0, #(_JB_FLOAT_BASE * 4)
vstmia r1, {d8-d15}
/* Store floating-point state */
fmrx r1, fpscr
str r1, [r0, #(_JB_FLOAT_STATE * 4)]
#endif /* __ARM_HAVE_VFP */
mov r0, #0x00000000
bx lr
END(_setjmp)
.L_setjmp_magic:
.word _JB_MAGIC__SETJMP
ENTRY(_longjmp)
ldr r2, .L_setjmp_magic
ldr r3, [r0, #(_JB_MAGIC * 4)]
teq r2, r3
bne botch
#ifdef __ARM_HAVE_VFP
/* Restore floating-point registers */
add r2, r0, #(_JB_FLOAT_BASE * 4)
vldmia r2, {d8-d15}
/* Restore floating-point state */
ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
fmxr fpscr, r2
#endif /* __ARM_HAVE_VFP */
/* Restore core registers */
add r2, r0, #(_JB_CORE_BASE * 4)
ldmia r2, {r4-r14}
/* Validate sp and r14 */
teq sp, #0
teqne r14, #0
beq botch
/* Set return value */
mov r0, r1
teq r0, #0x00000000
moveq r0, #0x00000001
bx lr
/* validation failed, die die die. */
botch:
bl PIC_SYM(longjmperror, PLT)
bl PIC_SYM(abort, PLT)
b . - 8 /* Cannot get here */
END(_longjmp)

View File

@ -40,5 +40,5 @@ ENTRY(abort)
.cfi_def_cfa_offset 8
.cfi_rel_offset r3, 0
.cfi_rel_offset r14, 4
bl __libc_android_abort
bl PIC_SYM(__libc_android_abort, PLT)
END(abort)

View File

@ -37,13 +37,7 @@
* the expectation that libc will define it and call through to
* a differently-named function in the dynamic linker.
*/
_Unwind_Ptr __gnu_Unwind_Find_exidx_impl(_Unwind_Ptr pc, int *pcount) {
_Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr pc, int *pcount)
{
return dl_unwind_find_exidx(pc, pcount);
}
_Unwind_Ptr __gnu_Unwind_Find_exidx_impl2(_Unwind_Ptr pc, int *pcount) {
return dl_unwind_find_exidx(pc, pcount);
}
__asm__(".symver __gnu_Unwind_Find_exidx_impl,__gnu_Unwind_Find_exidx@LIBC_PRIVATE");
__asm__(".symver __gnu_Unwind_Find_exidx_impl2,__gnu_Unwind_Find_exidx@@LIBC_N");

View File

@ -40,8 +40,6 @@
* Optimized memcmp() for Cortex-A9.
*/
.syntax unified
ENTRY(memcmp)
pld [r0, #(CACHE_LINE_SIZE * 0)]
pld [r0, #(CACHE_LINE_SIZE * 1)]
@ -163,25 +161,25 @@ ENTRY(memcmp)
eors r0, r0, ip
ldreq r0, [r4], #4
ldreq ip, [r1, #4]!
eorseq r0, r0, lr
eoreqs r0, r0, lr
ldreq r0, [r4], #4
ldreq lr, [r1, #4]!
eorseq r0, r0, ip
eoreqs r0, r0, ip
ldreq r0, [r4], #4
ldreq ip, [r1, #4]!
eorseq r0, r0, lr
eoreqs r0, r0, lr
ldreq r0, [r4], #4
ldreq lr, [r1, #4]!
eorseq r0, r0, ip
eoreqs r0, r0, ip
ldreq r0, [r4], #4
ldreq ip, [r1, #4]!
eorseq r0, r0, lr
eoreqs r0, r0, lr
ldreq r0, [r4], #4
ldreq lr, [r1, #4]!
eorseq r0, r0, ip
eoreqs r0, r0, ip
ldreq r0, [r4], #4
ldreq ip, [r1, #4]!
eorseq r0, r0, lr
eoreqs r0, r0, lr
bne 2f
subs r2, r2, #32
bhs 0b
@ -221,7 +219,8 @@ ENTRY(memcmp)
bne 8b
9: /* restore registers and return */
ldmfd sp!, {r4, pc}
ldmfd sp!, {r4, lr}
bx lr
10: /* process less than 12 bytes */
cmp r2, #0
@ -264,17 +263,17 @@ ENTRY(memcmp)
ldreq lr, [r1], #4
ldreq r0, [r4], #4
orreq ip, ip, lr, lsl #16
eorseq r0, r0, ip
eoreqs r0, r0, ip
moveq ip, lr, lsr #16
ldreq lr, [r1], #4
ldreq r0, [r4], #4
orreq ip, ip, lr, lsl #16
eorseq r0, r0, ip
eoreqs r0, r0, ip
moveq ip, lr, lsr #16
ldreq lr, [r1], #4
ldreq r0, [r4], #4
orreq ip, ip, lr, lsl #16
eorseq r0, r0, ip
eoreqs r0, r0, ip
bne 7f
subs r2, r2, #16
bhs 6b
@ -318,7 +317,7 @@ ENTRY(memcmp)
ldreq r7, [r1], #4
ldreq r0, [r4], #4
orreq ip, ip, r7, lsl r6
eorseq r0, r0, ip
eoreqs r0, r0, ip
bne 7f
subs r2, r2, #8
bhs 6b

View File

@ -0,0 +1,686 @@
/*
* Copyright (C) 2008 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 <machine/cpu-features.h>
#include <private/bionic_asm.h>
#if defined(__ARM_NEON__) && !defined(ARCH_ARM_USE_NON_NEON_MEMCPY)
.text
.fpu neon
#ifdef HAVE_32_BYTE_CACHE_LINE
/* a prefetch distance of 2 cache-lines */
#define CACHE_LINE_SIZE 32
#else
/* a prefetch distance of 4 cache-lines works best experimentally */
#define CACHE_LINE_SIZE 64
#endif
ENTRY(memcpy)
.save {r0, lr}
/* start preloading as early as possible */
pld [r1, #(CACHE_LINE_SIZE * 0)]
stmfd sp!, {r0, lr}
pld [r1, #(CACHE_LINE_SIZE * 1)]
/* If Neon supports unaligned access then remove the align code,
* unless a size limit has been specified.
*/
#ifndef NEON_UNALIGNED_ACCESS
/* do we have at least 16-bytes to copy (needed for alignment below) */
cmp r2, #16
blo 5f
/* check if buffers are aligned. If so, run arm-only version */
eor r3, r0, r1
ands r3, r3, #0x3
beq 11f
/* align destination to cache-line for the write-buffer */
rsb r3, r0, #0
ands r3, r3, #0xF
beq 2f
/* copy up to 15-bytes (count in r3) */
sub r2, r2, r3
movs ip, r3, lsl #31
ldrmib lr, [r1], #1
strmib lr, [r0], #1
ldrcsb ip, [r1], #1
ldrcsb lr, [r1], #1
strcsb ip, [r0], #1
strcsb lr, [r0], #1
movs ip, r3, lsl #29
bge 1f
// copies 4 bytes, destination 32-bits aligned
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
1: bcc 2f
// copies 8 bytes, destination 64-bits aligned
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0, :64]!
2:
/* preload immediately the next cache line, which we may need */
pld [r1, #(CACHE_LINE_SIZE * 0)]
pld [r1, #(CACHE_LINE_SIZE * 1)]
#ifdef HAVE_32_BYTE_CACHE_LINE
/* make sure we have at least 32 bytes to copy */
subs r2, r2, #32
blo 4f
/* preload all the cache lines we need.
* NOTE: the number of pld below depends on PREFETCH_DISTANCE,
* ideally would would increase the distance in the main loop to
* avoid the goofy code below. In practice this doesn't seem to make
* a big difference.
*/
pld [r1, #(PREFETCH_DISTANCE)]
1: /* The main loop copies 32 bytes at a time */
vld1.8 {d0 - d3}, [r1]!
pld [r1, #(PREFETCH_DISTANCE)]
subs r2, r2, #32
vst1.8 {d0 - d3}, [r0, :128]!
bhs 1b
#else
/* make sure we have at least 64 bytes to copy */
subs r2, r2, #64
blo 2f
/* preload all the cache lines we need. */
pld [r1, #(CACHE_LINE_SIZE * 2)]
pld [r1, #(CACHE_LINE_SIZE * 3)]
1: /* The main loop copies 64 bytes at a time */
vld1.8 {d0 - d3}, [r1]!
vld1.8 {d4 - d7}, [r1]!
#ifdef HAVE_32_BYTE_CACHE_LINE
pld [r1, #(CACHE_LINE_SIZE * 2)]
pld [r1, #(CACHE_LINE_SIZE * 3)]
#else
pld [r1, #(CACHE_LINE_SIZE * 3)]
#endif
subs r2, r2, #64
vst1.8 {d0 - d3}, [r0, :128]!
vst1.8 {d4 - d7}, [r0, :128]!
bhs 1b
2: /* fix-up the remaining count and make sure we have >= 32 bytes left */
add r2, r2, #64
subs r2, r2, #32
blo 4f
3: /* 32 bytes at a time. These cache lines were already preloaded */
vld1.8 {d0 - d3}, [r1]!
subs r2, r2, #32
vst1.8 {d0 - d3}, [r0, :128]!
bhs 3b
#endif
4: /* less than 32 left */
add r2, r2, #32
tst r2, #0x10
beq 5f
// copies 16 bytes, 128-bits aligned
vld1.8 {d0, d1}, [r1]!
vst1.8 {d0, d1}, [r0, :128]!
5: /* copy up to 15-bytes (count in r2) */
movs ip, r2, lsl #29
bcc 1f
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0]!
1: bge 2f
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
2: movs ip, r2, lsl #31
ldrmib r3, [r1], #1
ldrcsb ip, [r1], #1
ldrcsb lr, [r1], #1
strmib r3, [r0], #1
strcsb ip, [r0], #1
strcsb lr, [r0], #1
ldmfd sp!, {r0, lr}
bx lr
#else /* NEON_UNALIGNED_ACCESS */
// Check so divider is at least 16 bytes, needed for alignment code.
cmp r2, #16
blo 5f
#ifdef NEON_MEMCPY_ALIGNMENT_DIVIDER
/* Check the upper size limit for Neon unaligned memory access in memcpy */
#if NEON_MEMCPY_ALIGNMENT_DIVIDER >= 16
cmp r2, #NEON_MEMCPY_ALIGNMENT_DIVIDER
blo 3f
#endif
/* check if buffers are aligned. If so, run arm-only version */
eor r3, r0, r1
ands r3, r3, #0x3
beq 11f
/* align destination to 16 bytes for the write-buffer */
rsb r3, r0, #0
ands r3, r3, #0xF
beq 3f
/* copy up to 15-bytes (count in r3) */
sub r2, r2, r3
movs ip, r3, lsl #31
ldrmib lr, [r1], #1
strmib lr, [r0], #1
ldrcsb ip, [r1], #1
ldrcsb lr, [r1], #1
strcsb ip, [r0], #1
strcsb lr, [r0], #1
movs ip, r3, lsl #29
bge 1f
// copies 4 bytes, destination 32-bits aligned
vld1.32 {d0[0]}, [r1]!
vst1.32 {d0[0]}, [r0, :32]!
1: bcc 2f
// copies 8 bytes, destination 64-bits aligned
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0, :64]!
2:
/* preload immediately the next cache line, which we may need */
pld [r1, #(CACHE_LINE_SIZE * 0)]
pld [r1, #(CACHE_LINE_SIZE * 1)]
3:
#endif
/* make sure we have at least 64 bytes to copy */
subs r2, r2, #64
blo 2f
/* preload all the cache lines we need */
pld [r1, #(CACHE_LINE_SIZE * 2)]
pld [r1, #(CACHE_LINE_SIZE * 3)]
1: /* The main loop copies 64 bytes at a time */
vld1.8 {d0 - d3}, [r1]!
vld1.8 {d4 - d7}, [r1]!
#ifdef HAVE_32_BYTE_CACHE_LINE
pld [r1, #(CACHE_LINE_SIZE * 2)]
pld [r1, #(CACHE_LINE_SIZE * 3)]
#else
pld [r1, #(CACHE_LINE_SIZE * 3)]
#endif
subs r2, r2, #64
vst1.8 {d0 - d3}, [r0]!
vst1.8 {d4 - d7}, [r0]!
bhs 1b
2: /* fix-up the remaining count and make sure we have >= 32 bytes left */
add r2, r2, #64
subs r2, r2, #32
blo 4f
3: /* 32 bytes at a time. These cache lines were already preloaded */
vld1.8 {d0 - d3}, [r1]!
subs r2, r2, #32
vst1.8 {d0 - d3}, [r0]!
bhs 3b
4: /* less than 32 left */
add r2, r2, #32
tst r2, #0x10
beq 5f
// copies 16 bytes, 128-bits aligned
vld1.8 {d0, d1}, [r1]!
vst1.8 {d0, d1}, [r0]!
5: /* copy up to 15-bytes (count in r2) */
movs ip, r2, lsl #29
bcc 1f
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0]!
1: bge 2f
vld1.32 {d0[0]}, [r1]!
vst1.32 {d0[0]}, [r0]!
2: movs ip, r2, lsl #31
ldrmib r3, [r1], #1
ldrcsb ip, [r1], #1
ldrcsb lr, [r1], #1
strmib r3, [r0], #1
strcsb ip, [r0], #1
strcsb lr, [r0], #1
ldmfd sp!, {r0, lr}
bx lr
#endif /* NEON_UNALIGNED_ACCESS */
11:
/* Simple arm-only copy loop to handle aligned copy operations */
stmfd sp!, {r4, r5, r6, r7, r8}
pld [r1, #(CACHE_LINE_SIZE * 2)]
/* Check alignment */
rsb r3, r1, #0
ands r3, #3
beq 2f
/* align source to 32 bits. We need to insert 2 instructions between
* a ldr[b|h] and str[b|h] because byte and half-word instructions
* stall 2 cycles.
*/
movs r12, r3, lsl #31
sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */
ldrmib r3, [r1], #1
ldrcsb r4, [r1], #1
ldrcsb r5, [r1], #1
strmib r3, [r0], #1
strcsb r4, [r0], #1
strcsb r5, [r0], #1
2:
subs r2, #32
blt 5f
pld [r1, #(CACHE_LINE_SIZE * 3)]
3: /* Main copy loop, copying 32 bytes at a time */
pld [r1, #(CACHE_LINE_SIZE * 4)]
ldmia r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
subs r2, r2, #32
stmia r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
bge 3b
5: /* Handle any remaining bytes */
adds r2, #32
beq 6f
movs r12, r2, lsl #28
ldmcsia r1!, {r3, r4, r5, r6} /* 16 bytes */
ldmmiia r1!, {r7, r8} /* 8 bytes */
stmcsia r0!, {r3, r4, r5, r6}
stmmiia r0!, {r7, r8}
movs r12, r2, lsl #30
ldrcs r3, [r1], #4 /* 4 bytes */
ldrmih r4, [r1], #2 /* 2 bytes */
strcs r3, [r0], #4
strmih r4, [r0], #2
tst r2, #0x1
ldrneb r3, [r1] /* last byte */
strneb r3, [r0]
6:
ldmfd sp!, {r4, r5, r6, r7, r8}
ldmfd sp!, {r0, pc}
END(memcpy)
#else /* __ARM_ARCH__ < 7 */
/*
* Optimized memcpy() for ARM.
*
* note that memcpy() always returns the destination pointer,
* so we have to preserve R0.
*/
ENTRY(memcpy)
/* The stack must always be 64-bits aligned to be compliant with the
* ARM ABI. Since we have to save R0, we might as well save R4
* which we can use for better pipelining of the reads below
*/
.save {r0, r4, lr}
stmfd sp!, {r0, r4, lr}
/* Making room for r5-r11 which will be spilled later */
.pad #28
sub sp, sp, #28
// preload the destination because we'll align it to a cache line
// with small writes. Also start the source "pump".
pld [r0, #0]
pld [r1, #0]
pld [r1, #32]
/* it simplifies things to take care of len<4 early */
cmp r2, #4
blo copy_last_3_and_return
/* compute the offset to align the source
* offset = (4-(src&3))&3 = -src & 3
*/
rsb r3, r1, #0
ands r3, r3, #3
beq src_aligned
/* align source to 32 bits. We need to insert 2 instructions between
* a ldr[b|h] and str[b|h] because byte and half-word instructions
* stall 2 cycles.
*/
movs r12, r3, lsl #31
sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */
ldrmib r3, [r1], #1
ldrcsb r4, [r1], #1
ldrcsb r12,[r1], #1
strmib r3, [r0], #1
strcsb r4, [r0], #1
strcsb r12,[r0], #1
src_aligned:
/* see if src and dst are aligned together (congruent) */
eor r12, r0, r1
tst r12, #3
bne non_congruent
/* Use post-incriment mode for stm to spill r5-r11 to reserved stack
* frame. Don't update sp.
*/
stmea sp, {r5-r11}
/* align the destination to a cache-line */
rsb r3, r0, #0
ands r3, r3, #0x1C
beq congruent_aligned32
cmp r3, r2
andhi r3, r2, #0x1C
/* conditionnaly copies 0 to 7 words (length in r3) */
movs r12, r3, lsl #28
ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */
ldmmiia r1!, {r8, r9} /* 8 bytes */
stmcsia r0!, {r4, r5, r6, r7}
stmmiia r0!, {r8, r9}
tst r3, #0x4
ldrne r10,[r1], #4 /* 4 bytes */
strne r10,[r0], #4
sub r2, r2, r3
congruent_aligned32:
/*
* here source is aligned to 32 bytes.
*/
cached_aligned32:
subs r2, r2, #32
blo less_than_32_left
/*
* We preload a cache-line up to 64 bytes ahead. On the 926, this will
* stall only until the requested world is fetched, but the linefill
* continues in the the background.
* While the linefill is going, we write our previous cache-line
* into the write-buffer (which should have some free space).
* When the linefill is done, the writebuffer will
* start dumping its content into memory
*
* While all this is going, we then load a full cache line into
* 8 registers, this cache line should be in the cache by now
* (or partly in the cache).
*
* This code should work well regardless of the source/dest alignment.
*
*/
// Align the preload register to a cache-line because the cpu does
// "critical word first" (the first word requested is loaded first).
bic r12, r1, #0x1F
add r12, r12, #64
1: ldmia r1!, { r4-r11 }
pld [r12, #64]
subs r2, r2, #32
// NOTE: if r12 is more than 64 ahead of r1, the following ldrhi
// for ARM9 preload will not be safely guarded by the preceding subs.
// When it is safely guarded the only possibility to have SIGSEGV here
// is because the caller overstates the length.
ldrhi r3, [r12], #32 /* cheap ARM9 preload */
stmia r0!, { r4-r11 }
bhs 1b
add r2, r2, #32
less_than_32_left:
/*
* less than 32 bytes left at this point (length in r2)
*/
/* skip all this if there is nothing to do, which should
* be a common case (if not executed the code below takes
* about 16 cycles)
*/
tst r2, #0x1F
beq 1f
/* conditionnaly copies 0 to 31 bytes */
movs r12, r2, lsl #28
ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */
ldmmiia r1!, {r8, r9} /* 8 bytes */
stmcsia r0!, {r4, r5, r6, r7}
stmmiia r0!, {r8, r9}
movs r12, r2, lsl #30
ldrcs r3, [r1], #4 /* 4 bytes */
ldrmih r4, [r1], #2 /* 2 bytes */
strcs r3, [r0], #4
strmih r4, [r0], #2
tst r2, #0x1
ldrneb r3, [r1] /* last byte */
strneb r3, [r0]
/* we're done! restore everything and return */
1: ldmfd sp!, {r5-r11}
ldmfd sp!, {r0, r4, lr}
bx lr
/********************************************************************/
non_congruent:
/*
* here source is aligned to 4 bytes
* but destination is not.
*
* in the code below r2 is the number of bytes read
* (the number of bytes written is always smaller, because we have
* partial words in the shift queue)
*/
cmp r2, #4
blo copy_last_3_and_return
/* Use post-incriment mode for stm to spill r5-r11 to reserved stack
* frame. Don't update sp.
*/
stmea sp, {r5-r11}
/* compute shifts needed to align src to dest */
rsb r5, r0, #0
and r5, r5, #3 /* r5 = # bytes in partial words */
mov r12, r5, lsl #3 /* r12 = right */
rsb lr, r12, #32 /* lr = left */
/* read the first word */
ldr r3, [r1], #4
sub r2, r2, #4
/* write a partial word (0 to 3 bytes), such that destination
* becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
*/
movs r5, r5, lsl #31
strmib r3, [r0], #1
movmi r3, r3, lsr #8
strcsb r3, [r0], #1
movcs r3, r3, lsr #8
strcsb r3, [r0], #1
movcs r3, r3, lsr #8
cmp r2, #4
blo partial_word_tail
/* Align destination to 32 bytes (cache line boundary) */
1: tst r0, #0x1c
beq 2f
ldr r5, [r1], #4
sub r2, r2, #4
orr r4, r3, r5, lsl lr
mov r3, r5, lsr r12
str r4, [r0], #4
cmp r2, #4
bhs 1b
blo partial_word_tail
/* copy 32 bytes at a time */
2: subs r2, r2, #32
blo less_than_thirtytwo
/* Use immediate mode for the shifts, because there is an extra cycle
* for register shifts, which could account for up to 50% of
* performance hit.
*/
cmp r12, #24
beq loop24
cmp r12, #8
beq loop8
loop16:
ldr r12, [r1], #4
1: mov r4, r12
ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
pld [r1, #64]
subs r2, r2, #32
ldrhs r12, [r1], #4
orr r3, r3, r4, lsl #16
mov r4, r4, lsr #16
orr r4, r4, r5, lsl #16
mov r5, r5, lsr #16
orr r5, r5, r6, lsl #16
mov r6, r6, lsr #16
orr r6, r6, r7, lsl #16
mov r7, r7, lsr #16
orr r7, r7, r8, lsl #16
mov r8, r8, lsr #16
orr r8, r8, r9, lsl #16
mov r9, r9, lsr #16
orr r9, r9, r10, lsl #16
mov r10, r10, lsr #16
orr r10, r10, r11, lsl #16
stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
mov r3, r11, lsr #16
bhs 1b
b less_than_thirtytwo
loop8:
ldr r12, [r1], #4
1: mov r4, r12
ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
pld [r1, #64]
subs r2, r2, #32
ldrhs r12, [r1], #4
orr r3, r3, r4, lsl #24
mov r4, r4, lsr #8
orr r4, r4, r5, lsl #24
mov r5, r5, lsr #8
orr r5, r5, r6, lsl #24
mov r6, r6, lsr #8
orr r6, r6, r7, lsl #24
mov r7, r7, lsr #8
orr r7, r7, r8, lsl #24
mov r8, r8, lsr #8
orr r8, r8, r9, lsl #24
mov r9, r9, lsr #8
orr r9, r9, r10, lsl #24
mov r10, r10, lsr #8
orr r10, r10, r11, lsl #24
stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
mov r3, r11, lsr #8
bhs 1b
b less_than_thirtytwo
loop24:
ldr r12, [r1], #4
1: mov r4, r12
ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
pld [r1, #64]
subs r2, r2, #32
ldrhs r12, [r1], #4
orr r3, r3, r4, lsl #8
mov r4, r4, lsr #24
orr r4, r4, r5, lsl #8
mov r5, r5, lsr #24
orr r5, r5, r6, lsl #8
mov r6, r6, lsr #24
orr r6, r6, r7, lsl #8
mov r7, r7, lsr #24
orr r7, r7, r8, lsl #8
mov r8, r8, lsr #24
orr r8, r8, r9, lsl #8
mov r9, r9, lsr #24
orr r9, r9, r10, lsl #8
mov r10, r10, lsr #24
orr r10, r10, r11, lsl #8
stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
mov r3, r11, lsr #24
bhs 1b
less_than_thirtytwo:
/* copy the last 0 to 31 bytes of the source */
rsb r12, lr, #32 /* we corrupted r12, recompute it */
add r2, r2, #32
cmp r2, #4
blo partial_word_tail
1: ldr r5, [r1], #4
sub r2, r2, #4
orr r4, r3, r5, lsl lr
mov r3, r5, lsr r12
str r4, [r0], #4
cmp r2, #4
bhs 1b
partial_word_tail:
/* we have a partial word in the input buffer */
movs r5, lr, lsl #(31-3)
strmib r3, [r0], #1
movmi r3, r3, lsr #8
strcsb r3, [r0], #1
movcs r3, r3, lsr #8
strcsb r3, [r0], #1
/* Refill spilled registers from the stack. Don't update sp. */
ldmfd sp, {r5-r11}
copy_last_3_and_return:
movs r2, r2, lsl #31 /* copy remaining 0, 1, 2 or 3 bytes */
ldrmib r2, [r1], #1
ldrcsb r3, [r1], #1
ldrcsb r12,[r1]
strmib r2, [r0], #1
strcsb r3, [r0], #1
strcsb r12,[r0]
/* we're done! restore sp and spilled registers and return */
add sp, sp, #28
ldmfd sp!, {r0, r4, lr}
bx lr
END(memcpy)
#endif /* __ARM_ARCH__ < 7 */

View File

@ -0,0 +1,614 @@
/* Copyright (c) 2013, Linaro Limited
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 Linaro Limited 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
HOLDER 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.
*/
/*
This memcpy routine is optimised for Cortex-A15 cores and takes advantage
of VFP or NEON when built with the appropriate flags.
Assumptions:
ARMv6 (ARMv7-a if using Neon)
ARM state
Unaligned accesses
LDRD/STRD support unaligned word accesses
*/
#include <machine/cpu-features.h>
#include <private/bionic_asm.h>
.syntax unified
/* This implementation requires ARM state. */
.arm
#ifdef __ARM_NEON__
.fpu neon
.arch armv7-a
# define FRAME_SIZE 4
# define USE_VFP
# define USE_NEON
#elif !defined (__SOFTFP__)
.arch armv6
.fpu vfpv2
# define FRAME_SIZE 32
# define USE_VFP
#else
.arch armv6
# define FRAME_SIZE 32
#endif
/* Old versions of GAS incorrectly implement the NEON align semantics. */
#ifdef BROKEN_ASM_NEON_ALIGN
#define ALIGN(addr, align) addr,:align
#else
#define ALIGN(addr, align) addr:align
#endif
#define PC_OFFSET 8 /* PC pipeline compensation. */
#define INSN_SIZE 4
/* Call parameters. */
#define dstin r0
#define src r1
#define count r2
/* Locals. */
#define tmp1 r3
#define dst ip
#define tmp2 r10
#ifndef USE_NEON
/* For bulk copies using GP registers. */
#define A_l r2 /* Call-clobbered. */
#define A_h r3 /* Call-clobbered. */
#define B_l r4
#define B_h r5
#define C_l r6
#define C_h r7
#define D_l r8
#define D_h r9
#endif
/* Number of lines ahead to pre-fetch data. If you change this the code
below will need adjustment to compensate. */
#define prefetch_lines 5
#ifdef USE_VFP
.macro cpy_line_vfp vreg, base
vstr \vreg, [dst, #\base]
vldr \vreg, [src, #\base]
vstr d0, [dst, #\base + 8]
vldr d0, [src, #\base + 8]
vstr d1, [dst, #\base + 16]
vldr d1, [src, #\base + 16]
vstr d2, [dst, #\base + 24]
vldr d2, [src, #\base + 24]
vstr \vreg, [dst, #\base + 32]
vldr \vreg, [src, #\base + prefetch_lines * 64 - 32]
vstr d0, [dst, #\base + 40]
vldr d0, [src, #\base + 40]
vstr d1, [dst, #\base + 48]
vldr d1, [src, #\base + 48]
vstr d2, [dst, #\base + 56]
vldr d2, [src, #\base + 56]
.endm
.macro cpy_tail_vfp vreg, base
vstr \vreg, [dst, #\base]
vldr \vreg, [src, #\base]
vstr d0, [dst, #\base + 8]
vldr d0, [src, #\base + 8]
vstr d1, [dst, #\base + 16]
vldr d1, [src, #\base + 16]
vstr d2, [dst, #\base + 24]
vldr d2, [src, #\base + 24]
vstr \vreg, [dst, #\base + 32]
vstr d0, [dst, #\base + 40]
vldr d0, [src, #\base + 40]
vstr d1, [dst, #\base + 48]
vldr d1, [src, #\base + 48]
vstr d2, [dst, #\base + 56]
vldr d2, [src, #\base + 56]
.endm
#endif
.p2align 6
ENTRY(memcpy)
mov dst, dstin /* Preserve dstin, we need to return it. */
cmp count, #64
bge .Lcpy_not_short
/* Deal with small copies quickly by dropping straight into the
exit block. */
.Ltail63unaligned:
#ifdef USE_NEON
and tmp1, count, #0x38
rsb tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
add pc, pc, tmp1
vld1.8 {d0}, [src]! /* 14 words to go. */
vst1.8 {d0}, [dst]!
vld1.8 {d0}, [src]! /* 12 words to go. */
vst1.8 {d0}, [dst]!
vld1.8 {d0}, [src]! /* 10 words to go. */
vst1.8 {d0}, [dst]!
vld1.8 {d0}, [src]! /* 8 words to go. */
vst1.8 {d0}, [dst]!
vld1.8 {d0}, [src]! /* 6 words to go. */
vst1.8 {d0}, [dst]!
vld1.8 {d0}, [src]! /* 4 words to go. */
vst1.8 {d0}, [dst]!
vld1.8 {d0}, [src]! /* 2 words to go. */
vst1.8 {d0}, [dst]!
tst count, #4
ldrne tmp1, [src], #4
strne tmp1, [dst], #4
#else
/* Copy up to 15 full words of data. May not be aligned. */
/* Cannot use VFP for unaligned data. */
and tmp1, count, #0x3c
add dst, dst, tmp1
add src, src, tmp1
rsb tmp1, tmp1, #(60 - PC_OFFSET/2 + INSN_SIZE/2)
/* Jump directly into the sequence below at the correct offset. */
add pc, pc, tmp1, lsl #1
ldr tmp1, [src, #-60] /* 15 words to go. */
str tmp1, [dst, #-60]
ldr tmp1, [src, #-56] /* 14 words to go. */
str tmp1, [dst, #-56]
ldr tmp1, [src, #-52]
str tmp1, [dst, #-52]
ldr tmp1, [src, #-48] /* 12 words to go. */
str tmp1, [dst, #-48]
ldr tmp1, [src, #-44]
str tmp1, [dst, #-44]
ldr tmp1, [src, #-40] /* 10 words to go. */
str tmp1, [dst, #-40]
ldr tmp1, [src, #-36]
str tmp1, [dst, #-36]
ldr tmp1, [src, #-32] /* 8 words to go. */
str tmp1, [dst, #-32]
ldr tmp1, [src, #-28]
str tmp1, [dst, #-28]
ldr tmp1, [src, #-24] /* 6 words to go. */
str tmp1, [dst, #-24]
ldr tmp1, [src, #-20]
str tmp1, [dst, #-20]
ldr tmp1, [src, #-16] /* 4 words to go. */
str tmp1, [dst, #-16]
ldr tmp1, [src, #-12]
str tmp1, [dst, #-12]
ldr tmp1, [src, #-8] /* 2 words to go. */
str tmp1, [dst, #-8]
ldr tmp1, [src, #-4]
str tmp1, [dst, #-4]
#endif
lsls count, count, #31
ldrhcs tmp1, [src], #2
ldrbne src, [src] /* Src is dead, use as a scratch. */
strhcs tmp1, [dst], #2
strbne src, [dst]
bx lr
.Lcpy_not_short:
/* At least 64 bytes to copy, but don't know the alignment yet. */
str tmp2, [sp, #-FRAME_SIZE]!
and tmp2, src, #7
and tmp1, dst, #7
cmp tmp1, tmp2
bne .Lcpy_notaligned
#ifdef USE_VFP
/* Magic dust alert! Force VFP on Cortex-A9. Experiments show
that the FP pipeline is much better at streaming loads and
stores. This is outside the critical loop. */
vmov.f32 s0, s0
#endif
/* SRC and DST have the same mutual 32-bit alignment, but we may
still need to pre-copy some bytes to get to natural alignment.
We bring DST into full 64-bit alignment. */
lsls tmp2, dst, #29
beq 1f
rsbs tmp2, tmp2, #0
sub count, count, tmp2, lsr #29
ldrmi tmp1, [src], #4
strmi tmp1, [dst], #4
lsls tmp2, tmp2, #2
ldrhcs tmp1, [src], #2
ldrbne tmp2, [src], #1
strhcs tmp1, [dst], #2
strbne tmp2, [dst], #1
1:
subs tmp2, count, #64 /* Use tmp2 for count. */
blt .Ltail63aligned
cmp tmp2, #512
bge .Lcpy_body_long
.Lcpy_body_medium: /* Count in tmp2. */
#ifdef USE_VFP
1:
vldr d0, [src, #0]
subs tmp2, tmp2, #64
vldr d1, [src, #8]
vstr d0, [dst, #0]
vldr d0, [src, #16]
vstr d1, [dst, #8]
vldr d1, [src, #24]
vstr d0, [dst, #16]
vldr d0, [src, #32]
vstr d1, [dst, #24]
vldr d1, [src, #40]
vstr d0, [dst, #32]
vldr d0, [src, #48]
vstr d1, [dst, #40]
vldr d1, [src, #56]
vstr d0, [dst, #48]
add src, src, #64
vstr d1, [dst, #56]
add dst, dst, #64
bge 1b
tst tmp2, #0x3f
beq .Ldone
.Ltail63aligned: /* Count in tmp2. */
and tmp1, tmp2, #0x38
add dst, dst, tmp1
add src, src, tmp1
rsb tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
add pc, pc, tmp1
vldr d0, [src, #-56] /* 14 words to go. */
vstr d0, [dst, #-56]
vldr d0, [src, #-48] /* 12 words to go. */
vstr d0, [dst, #-48]
vldr d0, [src, #-40] /* 10 words to go. */
vstr d0, [dst, #-40]
vldr d0, [src, #-32] /* 8 words to go. */
vstr d0, [dst, #-32]
vldr d0, [src, #-24] /* 6 words to go. */
vstr d0, [dst, #-24]
vldr d0, [src, #-16] /* 4 words to go. */
vstr d0, [dst, #-16]
vldr d0, [src, #-8] /* 2 words to go. */
vstr d0, [dst, #-8]
#else
sub src, src, #8
sub dst, dst, #8
1:
ldrd A_l, A_h, [src, #8]
strd A_l, A_h, [dst, #8]
ldrd A_l, A_h, [src, #16]
strd A_l, A_h, [dst, #16]
ldrd A_l, A_h, [src, #24]
strd A_l, A_h, [dst, #24]
ldrd A_l, A_h, [src, #32]
strd A_l, A_h, [dst, #32]
ldrd A_l, A_h, [src, #40]
strd A_l, A_h, [dst, #40]
ldrd A_l, A_h, [src, #48]
strd A_l, A_h, [dst, #48]
ldrd A_l, A_h, [src, #56]
strd A_l, A_h, [dst, #56]
ldrd A_l, A_h, [src, #64]!
strd A_l, A_h, [dst, #64]!
subs tmp2, tmp2, #64
bge 1b
tst tmp2, #0x3f
bne 1f
ldr tmp2,[sp], #FRAME_SIZE
bx lr
1:
add src, src, #8
add dst, dst, #8
.Ltail63aligned: /* Count in tmp2. */
/* Copy up to 7 d-words of data. Similar to Ltail63unaligned, but
we know that the src and dest are 32-bit aligned so we can use
LDRD/STRD to improve efficiency. */
/* TMP2 is now negative, but we don't care about that. The bottom
six bits still tell us how many bytes are left to copy. */
and tmp1, tmp2, #0x38
add dst, dst, tmp1
add src, src, tmp1
rsb tmp1, tmp1, #(56 - PC_OFFSET + INSN_SIZE)
add pc, pc, tmp1
ldrd A_l, A_h, [src, #-56] /* 14 words to go. */
strd A_l, A_h, [dst, #-56]
ldrd A_l, A_h, [src, #-48] /* 12 words to go. */
strd A_l, A_h, [dst, #-48]
ldrd A_l, A_h, [src, #-40] /* 10 words to go. */
strd A_l, A_h, [dst, #-40]
ldrd A_l, A_h, [src, #-32] /* 8 words to go. */
strd A_l, A_h, [dst, #-32]
ldrd A_l, A_h, [src, #-24] /* 6 words to go. */
strd A_l, A_h, [dst, #-24]
ldrd A_l, A_h, [src, #-16] /* 4 words to go. */
strd A_l, A_h, [dst, #-16]
ldrd A_l, A_h, [src, #-8] /* 2 words to go. */
strd A_l, A_h, [dst, #-8]
#endif
tst tmp2, #4
ldrne tmp1, [src], #4
strne tmp1, [dst], #4
lsls tmp2, tmp2, #31 /* Count (tmp2) now dead. */
ldrhcs tmp1, [src], #2
ldrbne tmp2, [src]
strhcs tmp1, [dst], #2
strbne tmp2, [dst]
.Ldone:
ldr tmp2, [sp], #FRAME_SIZE
bx lr
.Lcpy_body_long: /* Count in tmp2. */
/* Long copy. We know that there's at least (prefetch_lines * 64)
bytes to go. */
#ifdef USE_VFP
/* Don't use PLD. Instead, read some data in advance of the current
copy position into a register. This should act like a PLD
operation but we won't have to repeat the transfer. */
vldr d3, [src, #0]
vldr d4, [src, #64]
vldr d5, [src, #128]
vldr d6, [src, #192]
vldr d7, [src, #256]
vldr d0, [src, #8]
vldr d1, [src, #16]
vldr d2, [src, #24]
add src, src, #32
subs tmp2, tmp2, #prefetch_lines * 64 * 2
blt 2f
1:
cpy_line_vfp d3, 0
cpy_line_vfp d4, 64
cpy_line_vfp d5, 128
add dst, dst, #3 * 64
add src, src, #3 * 64
cpy_line_vfp d6, 0
cpy_line_vfp d7, 64
add dst, dst, #2 * 64
add src, src, #2 * 64
subs tmp2, tmp2, #prefetch_lines * 64
bge 1b
2:
cpy_tail_vfp d3, 0
cpy_tail_vfp d4, 64
cpy_tail_vfp d5, 128
add src, src, #3 * 64
add dst, dst, #3 * 64
cpy_tail_vfp d6, 0
vstr d7, [dst, #64]
vldr d7, [src, #64]
vstr d0, [dst, #64 + 8]
vldr d0, [src, #64 + 8]
vstr d1, [dst, #64 + 16]
vldr d1, [src, #64 + 16]
vstr d2, [dst, #64 + 24]
vldr d2, [src, #64 + 24]
vstr d7, [dst, #64 + 32]
add src, src, #96
vstr d0, [dst, #64 + 40]
vstr d1, [dst, #64 + 48]
vstr d2, [dst, #64 + 56]
add dst, dst, #128
add tmp2, tmp2, #prefetch_lines * 64
b .Lcpy_body_medium
#else
/* Long copy. Use an SMS style loop to maximize the I/O
bandwidth of the core. We don't have enough spare registers
to synthesise prefetching, so use PLD operations. */
/* Pre-bias src and dst. */
sub src, src, #8
sub dst, dst, #8
pld [src, #8]
pld [src, #72]
subs tmp2, tmp2, #64
pld [src, #136]
ldrd A_l, A_h, [src, #8]
strd B_l, B_h, [sp, #8]
ldrd B_l, B_h, [src, #16]
strd C_l, C_h, [sp, #16]
ldrd C_l, C_h, [src, #24]
strd D_l, D_h, [sp, #24]
pld [src, #200]
ldrd D_l, D_h, [src, #32]!
b 1f
.p2align 6
2:
pld [src, #232]
strd A_l, A_h, [dst, #40]
ldrd A_l, A_h, [src, #40]
strd B_l, B_h, [dst, #48]
ldrd B_l, B_h, [src, #48]
strd C_l, C_h, [dst, #56]
ldrd C_l, C_h, [src, #56]
strd D_l, D_h, [dst, #64]!
ldrd D_l, D_h, [src, #64]!
subs tmp2, tmp2, #64
1:
strd A_l, A_h, [dst, #8]
ldrd A_l, A_h, [src, #8]
strd B_l, B_h, [dst, #16]
ldrd B_l, B_h, [src, #16]
strd C_l, C_h, [dst, #24]
ldrd C_l, C_h, [src, #24]
strd D_l, D_h, [dst, #32]
ldrd D_l, D_h, [src, #32]
bcs 2b
/* Save the remaining bytes and restore the callee-saved regs. */
strd A_l, A_h, [dst, #40]
add src, src, #40
strd B_l, B_h, [dst, #48]
ldrd B_l, B_h, [sp, #8]
strd C_l, C_h, [dst, #56]
ldrd C_l, C_h, [sp, #16]
strd D_l, D_h, [dst, #64]
ldrd D_l, D_h, [sp, #24]
add dst, dst, #72
tst tmp2, #0x3f
bne .Ltail63aligned
ldr tmp2, [sp], #FRAME_SIZE
bx lr
#endif
.Lcpy_notaligned:
pld [src]
pld [src, #64]
/* There's at least 64 bytes to copy, but there is no mutual
alignment. */
/* Bring DST to 64-bit alignment. */
lsls tmp2, dst, #29
pld [src, #(2 * 64)]
beq 1f
rsbs tmp2, tmp2, #0
sub count, count, tmp2, lsr #29
ldrmi tmp1, [src], #4
strmi tmp1, [dst], #4
lsls tmp2, tmp2, #2
ldrbne tmp1, [src], #1
ldrhcs tmp2, [src], #2
strbne tmp1, [dst], #1
strhcs tmp2, [dst], #2
1:
pld [src, #(3 * 64)]
subs count, count, #64
ldrmi tmp2, [sp], #FRAME_SIZE
bmi .Ltail63unaligned
pld [src, #(4 * 64)]
#ifdef USE_NEON
vld1.8 {d0-d3}, [src]!
vld1.8 {d4-d7}, [src]!
subs count, count, #64
bmi 2f
1:
pld [src, #(4 * 64)]
vst1.8 {d0-d3}, [ALIGN (dst, 64)]!
vld1.8 {d0-d3}, [src]!
vst1.8 {d4-d7}, [ALIGN (dst, 64)]!
vld1.8 {d4-d7}, [src]!
subs count, count, #64
bpl 1b
2:
vst1.8 {d0-d3}, [ALIGN (dst, 64)]!
vst1.8 {d4-d7}, [ALIGN (dst, 64)]!
ands count, count, #0x3f
#else
/* Use an SMS style loop to maximize the I/O bandwidth. */
sub src, src, #4
sub dst, dst, #8
subs tmp2, count, #64 /* Use tmp2 for count. */
ldr A_l, [src, #4]
ldr A_h, [src, #8]
strd B_l, B_h, [sp, #8]
ldr B_l, [src, #12]
ldr B_h, [src, #16]
strd C_l, C_h, [sp, #16]
ldr C_l, [src, #20]
ldr C_h, [src, #24]
strd D_l, D_h, [sp, #24]
ldr D_l, [src, #28]
ldr D_h, [src, #32]!
b 1f
.p2align 6
2:
pld [src, #(5 * 64) - (32 - 4)]
strd A_l, A_h, [dst, #40]
ldr A_l, [src, #36]
ldr A_h, [src, #40]
strd B_l, B_h, [dst, #48]
ldr B_l, [src, #44]
ldr B_h, [src, #48]
strd C_l, C_h, [dst, #56]
ldr C_l, [src, #52]
ldr C_h, [src, #56]
strd D_l, D_h, [dst, #64]!
ldr D_l, [src, #60]
ldr D_h, [src, #64]!
subs tmp2, tmp2, #64
1:
strd A_l, A_h, [dst, #8]
ldr A_l, [src, #4]
ldr A_h, [src, #8]
strd B_l, B_h, [dst, #16]
ldr B_l, [src, #12]
ldr B_h, [src, #16]
strd C_l, C_h, [dst, #24]
ldr C_l, [src, #20]
ldr C_h, [src, #24]
strd D_l, D_h, [dst, #32]
ldr D_l, [src, #28]
ldr D_h, [src, #32]
bcs 2b
/* Save the remaining bytes and restore the callee-saved regs. */
strd A_l, A_h, [dst, #40]
add src, src, #36
strd B_l, B_h, [dst, #48]
ldrd B_l, B_h, [sp, #8]
strd C_l, C_h, [dst, #56]
ldrd C_l, C_h, [sp, #16]
strd D_l, D_h, [dst, #64]
ldrd D_l, D_h, [sp, #24]
add dst, dst, #72
ands count, tmp2, #0x3f
#endif
ldr tmp2, [sp], #FRAME_SIZE
bne .Ltail63unaligned
bx lr
END(memcpy)

View File

@ -1,42 +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.
*/
// Export this to maintain ABI compatibilty with libgcc, since compiler-rt
// doesn't use a table-driven implementation of __popcount.
const unsigned char __popcount_tab[256] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3,
3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4,
3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4,
4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5,
3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2,
2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,
4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5,
5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5,
5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};

View File

@ -1,3 +1,6 @@
/* $OpenBSD: setjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $ */
/* $NetBSD: setjmp.S,v 1.5 2003/04/05 23:08:51 bjh21 Exp $ */
/*
* Copyright (c) 1997 Mark Brinicombe
* Copyright (c) 2010 Android Open Source Project.
@ -32,203 +35,119 @@
*/
#include <private/bionic_asm.h>
#include <machine/setjmp.h>
#include <machine/cpu-features.h>
// According to the ARM AAPCS document, we only need to save
// the following registers:
//
// Core r4-r14
//
// VFP d8-d15 (see section 5.1.2.1)
//
// Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine
// calls; registers s0-s15 (d0-d7, q0-q3) do not need to be preserved
// (and can be used for passing arguments or returning results in standard
// procedure-call variants). Registers d16-d31 (q8-q15), if present, do
// not need to be preserved.
//
// FPSCR saved because glibc does.
// The internal structure of a jmp_buf is totally private.
// Current layout (may change in the future):
//
// word name description
// 0 sigflag/cookie setjmp cookie in top 31 bits, signal mask flag in low bit
// 1 sigmask signal mask (not used with _setjmp / _longjmp)
// 2 float_base base of float registers (d8 to d15)
// 18 float_state floating-point status and control register
// 19 core_base base of core registers (r4 to r14)
// 30 reserved reserved entries (room to grow)
// 64
//
// NOTE: float_base must be at an even word index, since the
// FP registers will be loaded/stored with instructions
// that expect 8-byte alignment.
#define _JB_SIGFLAG 0
#define _JB_SIGMASK (_JB_SIGFLAG+1)
#define _JB_FLOAT_BASE (_JB_SIGMASK+1)
#define _JB_FLOAT_STATE (_JB_FLOAT_BASE + (15-8+1)*2)
#define _JB_CORE_BASE (_JB_FLOAT_STATE+1)
/*
* C library -- setjmp, longjmp
*
* longjmp(a,v)
* will generate a "return(v)" from the last call to
* setjmp(a)
* by restoring registers from the stack.
* The previous signal state is restored.
*/
ENTRY(setjmp)
mov r1, #1
b sigsetjmp
/* Block all signals and retrieve the old signal mask */
stmfd sp!, {r0, r14}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset r14, 4
mov r0, #0x00000000
bl PIC_SYM(sigblock, PLT)
mov r1, r0
ldmfd sp!, {r0, r14}
.cfi_def_cfa_offset 0
/* Store signal mask */
str r1, [r0, #(_JB_SIGMASK * 4)]
ldr r1, .Lsetjmp_magic
str r1, [r0, #(_JB_MAGIC * 4)]
/* Store core registers */
add r1, r0, #(_JB_CORE_BASE * 4)
stmia r1, {r4-r14}
#ifdef __ARM_HAVE_VFP
/* Store floating-point registers */
add r1, r0, #(_JB_FLOAT_BASE * 4)
vstmia r1, {d8-d15}
/* Store floating-point state */
fmrx r1, fpscr
str r1, [r0, #(_JB_FLOAT_STATE * 4)]
#endif /* __ARM_HAVE_VFP */
mov r0, #0x00000000
bx lr
END(setjmp)
ENTRY(_setjmp)
mov r1, #0
b sigsetjmp
END(_setjmp)
.Lsetjmp_magic:
.word _JB_MAGIC_SETJMP
#define MANGLE_REGISTERS 1
.macro m_mangle_registers reg
#if MANGLE_REGISTERS
eor r4, r4, \reg
eor r5, r5, \reg
eor r6, r6, \reg
eor r7, r7, \reg
eor r8, r8, \reg
eor r9, r9, \reg
eor r10, r10, \reg
eor r11, r11, \reg
eor r12, r12, \reg
eor r13, r13, \reg
eor r14, r14, \reg
ENTRY(longjmp)
ldr r2, .Lsetjmp_magic
ldr r3, [r0, #(_JB_MAGIC * 4)]
teq r2, r3
bne botch
/* Fetch signal mask */
ldr r2, [r0, #(_JB_SIGMASK * 4)]
/* Set signal mask */
stmfd sp!, {r0, r1, r14}
.cfi_def_cfa_offset 12
.cfi_rel_offset r0, 0
.cfi_rel_offset r1, 4
.cfi_rel_offset r14, 8
sub sp, sp, #4 /* align the stack */
.cfi_adjust_cfa_offset 4
mov r0, r2
bl PIC_SYM(sigsetmask, PLT)
add sp, sp, #4 /* unalign the stack */
.cfi_adjust_cfa_offset -4
ldmfd sp!, {r0, r1, r14}
.cfi_def_cfa_offset 0
#ifdef __ARM_HAVE_VFP
/* Restore floating-point registers */
add r2, r0, #(_JB_FLOAT_BASE * 4)
vldmia r2, {d8-d15}
/* Restore floating-point state */
ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
fmxr fpscr, r2
#endif /* __ARM_HAVE_VFP */
/* Restore core registers */
add r2, r0, #(_JB_CORE_BASE * 4)
ldmia r2, {r4-r14}
/* Validate sp and r14 */
teq sp, #0
teqne r14, #0
beq botch
/* Set return value */
mov r0, r1
teq r0, #0x00000000
moveq r0, #0x00000001
bx lr
#ifdef __ARM_26__
mov r15, r14
#else
mov r15, r14
#endif
.endm
.macro m_unmangle_registers reg
m_mangle_registers \reg
.endm
// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
ENTRY(sigsetjmp)
stmfd sp!, {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
mov r0, r1
bl __bionic_setjmp_cookie_get
mov r1, r0
ldmfd sp, {r0}
// Save the setjmp cookie for later.
bic r2, r1, #1
stmfd sp!, {r2}
.cfi_adjust_cfa_offset 4
// Record the setjmp cookie and whether or not we're saving the signal mask.
str r1, [r0, #(_JB_SIGFLAG * 4)]
// Do we need to save the signal mask?
tst r1, #1
beq 1f
// Align the stack.
sub sp, #4
.cfi_adjust_cfa_offset 4
// Save the current signal mask.
add r2, r0, #(_JB_SIGMASK * 4)
mov r0, #2 // SIG_SETMASK
mov r1, #0
bl sigprocmask
// Unalign the stack.
add sp, #4
.cfi_adjust_cfa_offset -4
1:
ldmfd sp!, {r2}
.cfi_adjust_cfa_offset -4
ldmfd sp!, {r0, lr}
.cfi_adjust_cfa_offset -8
.cfi_restore r0
.cfi_restore lr
// Save core registers.
add r1, r0, #(_JB_CORE_BASE * 4)
m_mangle_registers r2
// ARM deprecates using sp in the register list for stmia.
stmia r1, {r4-r12, lr}
str sp, [r1, #(10 * 4)]
m_unmangle_registers r2
// Save floating-point registers.
add r1, r0, #(_JB_FLOAT_BASE * 4)
vstmia r1, {d8-d15}
// Save floating-point state.
fmrx r1, fpscr
str r1, [r0, #(_JB_FLOAT_STATE * 4)]
mov r0, #0
bx lr
END(sigsetjmp)
// void siglongjmp(sigjmp_buf env, int value);
ENTRY(siglongjmp)
stmfd sp!, {r0, r1, lr}
.cfi_def_cfa_offset 12
.cfi_rel_offset r0, 0
.cfi_rel_offset r1, 4
.cfi_rel_offset lr, 8
// Fetch the signal flag.
ldr r1, [r0, #(_JB_SIGFLAG * 4)]
// Do we need to restore the signal mask?
ands r1, r1, #1
beq 1f
// Restore the signal mask.
ldr r0, [r0, #(_JB_SIGMASK * 4)]
bl sigsetmask
1:
ldmfd sp!, {r0, r1, lr}
.cfi_adjust_cfa_offset -12
.cfi_restore r0
.cfi_restore r1
.cfi_restore lr
// Restore floating-point registers.
add r2, r0, #(_JB_FLOAT_BASE * 4)
vldmia r2, {d8-d15}
// Restore floating-point state.
ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
fmxr fpscr, r2
// Restore core registers.
ldr r3, [r0, #(_JB_SIGFLAG * 4)]
bic r3, r3, #1
add r2, r0, #(_JB_CORE_BASE * 4)
// ARM deprecates using sp in the register list for ldmia.
ldmia r2, {r4-r12, lr}
ldr sp, [r2, #(10 * 4)]
m_unmangle_registers r3
// Save the return value/address and check the setjmp cookie.
stmfd sp!, {r1, lr}
.cfi_adjust_cfa_offset 8
.cfi_rel_offset lr, 4
mov r0, r3
bl __bionic_setjmp_cookie_check
// Restore return value/address.
ldmfd sp!, {r0, lr}
.cfi_adjust_cfa_offset -8
.cfi_restore lr
teq r0, #0
moveq r0, #1
bx lr
END(siglongjmp)
ALIAS_SYMBOL(longjmp, siglongjmp)
ALIAS_SYMBOL(_longjmp, siglongjmp)
/* validation failed, die die die. */
botch:
bl PIC_SYM(longjmperror, PLT)
bl PIC_SYM(abort, PLT)
b . - 8 /* Cannot get here */
END(longjmp)

View File

@ -0,0 +1,66 @@
/* $OpenBSD: sigsetjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $ */
/* $NetBSD: sigsetjmp.S,v 1.3 2002/08/17 19:54:30 thorpej Exp $ */
/*
* Copyright (c) 1997 Mark Brinicombe
* All rights reserved.
*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Mark Brinicombe
* 4. 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 AUTHOR 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 AUTHOR 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.
*/
#define _ALIGN_TEXT .align 0
#include <private/bionic_asm.h>
#include <machine/setjmp.h>
/*
* C library -- sigsetjmp, siglongjmp
*
* longjmp(a,v)
* will generate a "return(v)" from the last call to
* setjmp(a, m)
* by restoring registers from the stack.
* The previous signal state is restored.
*/
ENTRY(sigsetjmp)
teq r1, #0
beq PIC_SYM(_setjmp, PLT)
b PIC_SYM(setjmp, PLT)
END(sigsetjmp)
.L_setjmp_magic:
.word _JB_MAGIC__SETJMP
ENTRY(siglongjmp)
ldr r2, .L_setjmp_magic
ldr r3, [r0]
teq r2, r3
beq PIC_SYM(_longjmp, PLT)
b PIC_SYM(longjmp, PLT)
END(siglongjmp)

View File

@ -0,0 +1,317 @@
/*
* Copyright (c) 2011 The Android Open Source Project
* Copyright (c) 2008 ARM Ltd
* All rights reserved.
*
* 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. The name of the company may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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 <machine/cpu-features.h>
#include <private/bionic_asm.h>
.text
#ifdef __ARMEB__
#define SHFT2LSB lsl
#define SHFT2LSBEQ lsleq
#define SHFT2MSB lsr
#define SHFT2MSBEQ lsreq
#define MSB 0x000000ff
#define LSB 0xff000000
#else
#define SHFT2LSB lsr
#define SHFT2LSBEQ lsreq
#define SHFT2MSB lsl
#define SHFT2MSBEQ lsleq
#define MSB 0xff000000
#define LSB 0x000000ff
#endif
#define magic1(REG) REG
#define magic2(REG) REG, lsl #7
ENTRY(strcmp)
pld [r0, #0]
pld [r1, #0]
eor r2, r0, r1
tst r2, #3
/* Strings not at same byte offset from a word boundary. */
bne .Lstrcmp_unaligned
ands r2, r0, #3
bic r0, r0, #3
bic r1, r1, #3
ldr ip, [r0], #4
it eq
ldreq r3, [r1], #4
beq 1f
/* Although s1 and s2 have identical initial alignment, they are
* not currently word aligned. Rather than comparing bytes,
* make sure that any bytes fetched from before the addressed
* bytes are forced to 0xff. Then they will always compare
* equal.
*/
eor r2, r2, #3
lsl r2, r2, #3
mvn r3, #MSB
SHFT2LSB r2, r3, r2
ldr r3, [r1], #4
orr ip, ip, r2
orr r3, r3, r2
1:
/* Load the 'magic' constant 0x01010101. */
str r4, [sp, #-4]!
mov r4, #1
orr r4, r4, r4, lsl #8
orr r4, r4, r4, lsl #16
.p2align 2
4:
pld [r0, #8]
pld [r1, #8]
sub r2, ip, magic1(r4)
cmp ip, r3
itttt eq
/* check for any zero bytes in first word */
biceq r2, r2, ip
tsteq r2, magic2(r4)
ldreq ip, [r0], #4
ldreq r3, [r1], #4
beq 4b
2:
/* There's a zero or a different byte in the word */
SHFT2MSB r0, ip, #24
SHFT2LSB ip, ip, #8
cmp r0, #1
it cs
cmpcs r0, r3, SHFT2MSB #24
it eq
SHFT2LSBEQ r3, r3, #8
beq 2b
/* On a big-endian machine, r0 contains the desired byte in bits
* 0-7; on a little-endian machine they are in bits 24-31. In
* both cases the other bits in r0 are all zero. For r3 the
* interesting byte is at the other end of the word, but the
* other bits are not necessarily zero. We need a signed result
* representing the differnece in the unsigned bytes, so for the
* little-endian case we can't just shift the interesting bits up.
*/
#ifdef __ARMEB__
sub r0, r0, r3, lsr #24
#else
and r3, r3, #255
/* No RSB instruction in Thumb2 */
#ifdef __thumb2__
lsr r0, r0, #24
sub r0, r0, r3
#else
rsb r0, r3, r0, lsr #24
#endif
#endif
ldr r4, [sp], #4
bx lr
.Lstrcmp_unaligned:
wp1 .req r0
wp2 .req r1
b1 .req r2
w1 .req r4
w2 .req r5
t1 .req ip
@ r3 is scratch
/* First of all, compare bytes until wp1(sp1) is word-aligned. */
1:
tst wp1, #3
beq 2f
ldrb r2, [wp1], #1
ldrb r3, [wp2], #1
cmp r2, #1
it cs
cmpcs r2, r3
beq 1b
sub r0, r2, r3
bx lr
2:
str r5, [sp, #-4]!
str r4, [sp, #-4]!
mov b1, #1
orr b1, b1, b1, lsl #8
orr b1, b1, b1, lsl #16
and t1, wp2, #3
bic wp2, wp2, #3
ldr w1, [wp1], #4
ldr w2, [wp2], #4
cmp t1, #2
beq 2f
bhi 3f
/* Critical inner Loop: Block with 3 bytes initial overlap */
.p2align 2
1:
bic t1, w1, #MSB
cmp t1, w2, SHFT2LSB #8
sub r3, w1, b1
bic r3, r3, w1
bne 4f
ands r3, r3, b1, lsl #7
it eq
ldreq w2, [wp2], #4
bne 5f
eor t1, t1, w1
cmp t1, w2, SHFT2MSB #24
bne 6f
ldr w1, [wp1], #4
b 1b
4:
SHFT2LSB w2, w2, #8
b 8f
5:
#ifdef __ARMEB__
/* The syndrome value may contain false ones if the string ends
* with the bytes 0x01 0x00
*/
tst w1, #0xff000000
itt ne
tstne w1, #0x00ff0000
tstne w1, #0x0000ff00
beq 7f
#else
bics r3, r3, #0xff000000
bne 7f
#endif
ldrb w2, [wp2]
SHFT2LSB t1, w1, #24
#ifdef __ARMEB__
lsl w2, w2, #24
#endif
b 8f
6:
SHFT2LSB t1, w1, #24
and w2, w2, #LSB
b 8f
/* Critical inner Loop: Block with 2 bytes initial overlap */
.p2align 2
2:
SHFT2MSB t1, w1, #16
sub r3, w1, b1
SHFT2LSB t1, t1, #16
bic r3, r3, w1
cmp t1, w2, SHFT2LSB #16
bne 4f
ands r3, r3, b1, lsl #7
it eq
ldreq w2, [wp2], #4
bne 5f
eor t1, t1, w1
cmp t1, w2, SHFT2MSB #16
bne 6f
ldr w1, [wp1], #4
b 2b
5:
#ifdef __ARMEB__
/* The syndrome value may contain false ones if the string ends
* with the bytes 0x01 0x00
*/
tst w1, #0xff000000
it ne
tstne w1, #0x00ff0000
beq 7f
#else
lsls r3, r3, #16
bne 7f
#endif
ldrh w2, [wp2]
SHFT2LSB t1, w1, #16
#ifdef __ARMEB__
lsl w2, w2, #16
#endif
b 8f
6:
SHFT2MSB w2, w2, #16
SHFT2LSB t1, w1, #16
4:
SHFT2LSB w2, w2, #16
b 8f
/* Critical inner Loop: Block with 1 byte initial overlap */
.p2align 2
3:
and t1, w1, #LSB
cmp t1, w2, SHFT2LSB #24
sub r3, w1, b1
bic r3, r3, w1
bne 4f
ands r3, r3, b1, lsl #7
it eq
ldreq w2, [wp2], #4
bne 5f
eor t1, t1, w1
cmp t1, w2, SHFT2MSB #8
bne 6f
ldr w1, [wp1], #4
b 3b
4:
SHFT2LSB w2, w2, #24
b 8f
5:
/* The syndrome value may contain false ones if the string ends
* with the bytes 0x01 0x00
*/
tst w1, #LSB
beq 7f
ldr w2, [wp2], #4
6:
SHFT2LSB t1, w1, #8
bic w2, w2, #MSB
b 8f
7:
mov r0, #0
ldr r4, [sp], #4
ldr r5, [sp], #4
bx lr
8:
and r2, t1, #LSB
and r0, w2, #LSB
cmp r0, #1
it cs
cmpcs r0, r2
itt eq
SHFT2LSBEQ t1, t1, #8
SHFT2LSBEQ w2, w2, #8
beq 8b
sub r0, r2, r0
ldr r4, [sp], #4
ldr r5, [sp], #4
bx lr
END(strcmp)

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2013 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,7 +26,191 @@
* SUCH DAMAGE.
*/
// Indicate which memcpy base file to include.
#define MEMCPY_BASE "memcpy_base.S"
#include <private/bionic_asm.h>
#include <private/libc_events.h>
#include "__strcat_chk_common.S"
.syntax unified
.thumb
.thumb_func
// Get the length of src string, then get the source of the dst string.
// Check that the two lengths together don't exceed the threshold, then
// do a memcpy of the data.
ENTRY(__strcat_chk)
pld [r0, #0]
push {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
push {r4, r5}
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
mov lr, r2
// Save the dst register to r5
mov r5, r0
// Zero out r4
eor r4, r4, r4
// r1 contains the address of the string to count.
.L_strlen_start:
mov r0, r1
ands r3, r1, #7
beq .L_mainloop
// Align to a double word (64 bits).
rsb r3, r3, #8
lsls ip, r3, #31
beq .L_align_to_32
ldrb r2, [r1], #1
cbz r2, .L_update_count_and_finish
.L_align_to_32:
bcc .L_align_to_64
ands ip, r3, #2
beq .L_align_to_64
ldrb r2, [r1], #1
cbz r2, .L_update_count_and_finish
ldrb r2, [r1], #1
cbz r2, .L_update_count_and_finish
.L_align_to_64:
tst r3, #4
beq .L_mainloop
ldr r3, [r1], #4
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_zero_in_second_register
.p2align 2
.L_mainloop:
ldrd r2, r3, [r1], #8
pld [r1, #64]
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .L_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_zero_in_second_register
b .L_mainloop
.L_update_count_and_finish:
sub r3, r1, r0
sub r3, r3, #1
b .L_finish
.L_zero_in_first_register:
sub r3, r1, r0
lsls r2, ip, #17
bne .L_sub8_and_finish
bcs .L_sub7_and_finish
lsls ip, ip, #1
bne .L_sub6_and_finish
sub r3, r3, #5
b .L_finish
.L_sub8_and_finish:
sub r3, r3, #8
b .L_finish
.L_sub7_and_finish:
sub r3, r3, #7
b .L_finish
.L_sub6_and_finish:
sub r3, r3, #6
b .L_finish
.L_zero_in_second_register:
sub r3, r1, r0
lsls r2, ip, #17
bne .L_sub4_and_finish
bcs .L_sub3_and_finish
lsls ip, ip, #1
bne .L_sub2_and_finish
sub r3, r3, #1
b .L_finish
.L_sub4_and_finish:
sub r3, r3, #4
b .L_finish
.L_sub3_and_finish:
sub r3, r3, #3
b .L_finish
.L_sub2_and_finish:
sub r3, r3, #2
.L_finish:
cmp r4, #0
bne .L_strlen_done
// Time to get the dst string length.
mov r1, r5
// Save the original source address to r5.
mov r5, r0
// Save the current length (adding 1 for the terminator).
add r4, r3, #1
b .L_strlen_start
// r0 holds the pointer to the dst string.
// r3 holds the dst string length.
// r4 holds the src string length + 1.
.L_strlen_done:
add r2, r3, r4
cmp r2, lr
bhi __strcat_chk_failed
// Set up the registers for the memcpy code.
mov r1, r5
pld [r1, #64]
mov r2, r4
add r0, r0, r3
pop {r4, r5}
END(__strcat_chk)
#define MEMCPY_BASE __strcat_chk_memcpy_base
#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
#include "memcpy_base.S"
ENTRY_PRIVATE(__strcat_chk_failed)
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
ldr r0, error_message
ldr r1, error_code
1:
add r0, pc
bl __fortify_chk_fail
error_code:
.word BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+4)
END(__strcat_chk_failed)
.data
error_string:
.string "strcat: prevented write past end of buffer"

View File

@ -1,212 +0,0 @@
/*
* Copyright (C) 2013 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 <private/bionic_asm.h>
#include <private/libc_events.h>
.syntax unified
.thumb
.thumb_func
// Get the length of src string, then get the source of the dst string.
// Check that the two lengths together don't exceed the threshold, then
// do a memcpy of the data.
ENTRY(__strcat_chk)
pld [r0, #0]
push {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
push {r4, r5}
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
mov lr, r2
// Save the dst register to r5
mov r5, r0
// Zero out r4
eor r4, r4, r4
// r1 contains the address of the string to count.
.L_strlen_start:
mov r0, r1
ands r3, r1, #7
beq .L_mainloop
// Align to a double word (64 bits).
rsb r3, r3, #8
lsls ip, r3, #31
beq .L_align_to_32
ldrb r2, [r1], #1
cbz r2, .L_update_count_and_finish
.L_align_to_32:
bcc .L_align_to_64
ands ip, r3, #2
beq .L_align_to_64
ldrb r2, [r1], #1
cbz r2, .L_update_count_and_finish
ldrb r2, [r1], #1
cbz r2, .L_update_count_and_finish
.L_align_to_64:
tst r3, #4
beq .L_mainloop
ldr r3, [r1], #4
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_zero_in_second_register
.p2align 2
.L_mainloop:
ldrd r2, r3, [r1], #8
pld [r1, #64]
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .L_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_zero_in_second_register
b .L_mainloop
.L_update_count_and_finish:
sub r3, r1, r0
sub r3, r3, #1
b .L_finish
.L_zero_in_first_register:
sub r3, r1, r0
lsls r2, ip, #17
bne .L_sub8_and_finish
bcs .L_sub7_and_finish
lsls ip, ip, #1
bne .L_sub6_and_finish
sub r3, r3, #5
b .L_finish
.L_sub8_and_finish:
sub r3, r3, #8
b .L_finish
.L_sub7_and_finish:
sub r3, r3, #7
b .L_finish
.L_sub6_and_finish:
sub r3, r3, #6
b .L_finish
.L_zero_in_second_register:
sub r3, r1, r0
lsls r2, ip, #17
bne .L_sub4_and_finish
bcs .L_sub3_and_finish
lsls ip, ip, #1
bne .L_sub2_and_finish
sub r3, r3, #1
b .L_finish
.L_sub4_and_finish:
sub r3, r3, #4
b .L_finish
.L_sub3_and_finish:
sub r3, r3, #3
b .L_finish
.L_sub2_and_finish:
sub r3, r3, #2
.L_finish:
cmp r4, #0
bne .L_strlen_done
// Time to get the dst string length.
mov r1, r5
// Save the original source address to r5.
mov r5, r0
// Save the current length (adding 1 for the terminator).
add r4, r3, #1
b .L_strlen_start
// r0 holds the pointer to the dst string.
// r3 holds the dst string length.
// r4 holds the src string length + 1.
.L_strlen_done:
add r2, r3, r4
cmp r2, lr
bhi .L_strcat_chk_failed
// Set up the registers for the memcpy code.
mov r1, r5
pld [r1, #64]
mov r2, r4
add r0, r0, r3
pop {r4, r5}
.cfi_adjust_cfa_offset -8
.cfi_restore r4
.cfi_restore r5
#include MEMCPY_BASE
// Undo the above cfi directives
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
.L_strcat_chk_failed:
ldr r0, error_message
ldr r1, error_code
1:
add r0, pc
bl __fortify_chk_fail
error_code:
.word BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+4)
END(__strcat_chk)
.data
error_string:
.string "strcat: prevented write past end of buffer"

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2013 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,7 +26,155 @@
* SUCH DAMAGE.
*/
// Indicate which memcpy base file to include.
#define MEMCPY_BASE "memcpy_base.S"
#include <private/bionic_asm.h>
#include <private/libc_events.h>
#include "__strcpy_chk_common.S"
.syntax unified
.thumb
.thumb_func
// Get the length of the source string first, then do a memcpy of the data
// instead of a strcpy.
ENTRY(__strcpy_chk)
pld [r0, #0]
push {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
mov lr, r2
mov r0, r1
ands r3, r1, #7
beq .L_mainloop
// Align to a double word (64 bits).
rsb r3, r3, #8
lsls ip, r3, #31
beq .L_align_to_32
ldrb r2, [r0], #1
cbz r2, .L_update_count_and_finish
.L_align_to_32:
bcc .L_align_to_64
ands ip, r3, #2
beq .L_align_to_64
ldrb r2, [r0], #1
cbz r2, .L_update_count_and_finish
ldrb r2, [r0], #1
cbz r2, .L_update_count_and_finish
.L_align_to_64:
tst r3, #4
beq .L_mainloop
ldr r3, [r0], #4
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_zero_in_second_register
.p2align 2
.L_mainloop:
ldrd r2, r3, [r0], #8
pld [r0, #64]
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .L_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_zero_in_second_register
b .L_mainloop
.L_update_count_and_finish:
sub r3, r0, r1
sub r3, r3, #1
b .L_check_size
.L_zero_in_first_register:
sub r3, r0, r1
lsls r2, ip, #17
bne .L_sub8_and_finish
bcs .L_sub7_and_finish
lsls ip, ip, #1
bne .L_sub6_and_finish
sub r3, r3, #5
b .L_check_size
.L_sub8_and_finish:
sub r3, r3, #8
b .L_check_size
.L_sub7_and_finish:
sub r3, r3, #7
b .L_check_size
.L_sub6_and_finish:
sub r3, r3, #6
b .L_check_size
.L_zero_in_second_register:
sub r3, r0, r1
lsls r2, ip, #17
bne .L_sub4_and_finish
bcs .L_sub3_and_finish
lsls ip, ip, #1
bne .L_sub2_and_finish
sub r3, r3, #1
b .L_check_size
.L_sub4_and_finish:
sub r3, r3, #4
b .L_check_size
.L_sub3_and_finish:
sub r3, r3, #3
b .L_check_size
.L_sub2_and_finish:
sub r3, r3, #2
.L_check_size:
pld [r1, #0]
pld [r1, #64]
ldr r0, [sp]
cmp r3, lr
bhs __strcpy_chk_failed
// Add 1 for copy length to get the string terminator.
add r2, r3, #1
END(__strcpy_chk)
#define MEMCPY_BASE __strcpy_chk_memcpy_base
#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
#include "memcpy_base.S"
ENTRY_PRIVATE(__strcpy_chk_failed)
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
ldr r0, error_message
ldr r1, error_code
1:
add r0, pc
bl __fortify_chk_fail
error_code:
.word BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+4)
END(__strcpy_chk_failed)
.data
error_string:
.string "strcpy: prevented write past end of buffer"

View File

@ -1,173 +0,0 @@
/*
* Copyright (C) 2013 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 <private/bionic_asm.h>
#include <private/libc_events.h>
.syntax unified
.thumb
.thumb_func
// Get the length of the source string first, then do a memcpy of the data
// instead of a strcpy.
ENTRY(__strcpy_chk)
pld [r0, #0]
push {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
mov lr, r2
mov r0, r1
ands r3, r1, #7
beq .L_mainloop
// Align to a double word (64 bits).
rsb r3, r3, #8
lsls ip, r3, #31
beq .L_align_to_32
ldrb r2, [r0], #1
cbz r2, .L_update_count_and_finish
.L_align_to_32:
bcc .L_align_to_64
ands ip, r3, #2
beq .L_align_to_64
ldrb r2, [r0], #1
cbz r2, .L_update_count_and_finish
ldrb r2, [r0], #1
cbz r2, .L_update_count_and_finish
.L_align_to_64:
tst r3, #4
beq .L_mainloop
ldr r3, [r0], #4
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_zero_in_second_register
.p2align 2
.L_mainloop:
ldrd r2, r3, [r0], #8
pld [r0, #64]
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .L_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_zero_in_second_register
b .L_mainloop
.L_update_count_and_finish:
sub r3, r0, r1
sub r3, r3, #1
b .L_check_size
.L_zero_in_first_register:
sub r3, r0, r1
lsls r2, ip, #17
bne .L_sub8_and_finish
bcs .L_sub7_and_finish
lsls ip, ip, #1
bne .L_sub6_and_finish
sub r3, r3, #5
b .L_check_size
.L_sub8_and_finish:
sub r3, r3, #8
b .L_check_size
.L_sub7_and_finish:
sub r3, r3, #7
b .L_check_size
.L_sub6_and_finish:
sub r3, r3, #6
b .L_check_size
.L_zero_in_second_register:
sub r3, r0, r1
lsls r2, ip, #17
bne .L_sub4_and_finish
bcs .L_sub3_and_finish
lsls ip, ip, #1
bne .L_sub2_and_finish
sub r3, r3, #1
b .L_check_size
.L_sub4_and_finish:
sub r3, r3, #4
b .L_check_size
.L_sub3_and_finish:
sub r3, r3, #3
b .L_check_size
.L_sub2_and_finish:
sub r3, r3, #2
.L_check_size:
pld [r1, #0]
pld [r1, #64]
ldr r0, [sp]
cmp r3, lr
bhs .L_strcpy_chk_failed
// Add 1 for copy length to get the string terminator.
add r2, r3, #1
#include MEMCPY_BASE
.L_strcpy_chk_failed:
ldr r0, error_message
ldr r1, error_code
1:
add r0, pc
bl __fortify_chk_fail
error_code:
.word BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+4)
END(__strcpy_chk)
.data
error_string:
.string "strcpy: prevented write past end of buffer"

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 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,8 +25,79 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 2013 ARM Ltd
* All rights reserved.
*
* 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. The name of the company may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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.
*/
// Indicate which memcpy base file to include.
#define MEMCPY_BASE "memcpy_base.S"
// Prototype: void *memcpy (void *dst, const void *src, size_t count).
#include "memcpy_common.S"
#include <private/bionic_asm.h>
#include <private/libc_events.h>
.text
.syntax unified
.fpu neon
ENTRY(__memcpy_chk)
cmp r2, r3
bhi __memcpy_chk_fail
// Fall through to memcpy...
END(__memcpy_chk)
ENTRY(memcpy)
pld [r1, #64]
push {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
END(memcpy)
#define MEMCPY_BASE __memcpy_base
#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
#include "memcpy_base.S"
ENTRY_PRIVATE(__memcpy_chk_fail)
// Preserve lr for backtrace.
push {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
ldr r0, error_message
ldr r1, error_code
1:
add r0, pc
bl __fortify_chk_fail
error_code:
.word BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+8)
END(__memcpy_chk_fail)
.data
error_string:
.string "memcpy: prevented write past end of buffer"

View File

@ -53,7 +53,11 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
.L_memcpy_base:
ENTRY_PRIVATE(MEMCPY_BASE)
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
// Assumes that n >= 0, and dst, src are valid pointers.
// For any sizes less than 832 use the neon code that doesn't
// care about the src alignment. This avoids any checks
@ -164,6 +168,12 @@
eor r3, r0, r1
ands r3, r3, #0x3
bne .L_copy_unknown_alignment
END(MEMCPY_BASE)
ENTRY_PRIVATE(MEMCPY_BASE_ALIGNED)
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
// To try and improve performance, stack layout changed,
// i.e., not keeping the stack looking like users expect
@ -175,7 +185,7 @@
strd r6, r7, [sp, #-8]!
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r6, 0
.cfi_rel_offset r7, 4
.cfi_rel_offset r7, 0
strd r8, r9, [sp, #-8]!
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r8, 0
@ -281,28 +291,10 @@
// Restore registers: optimized pop {r0, pc}
ldrd r8, r9, [sp], #8
.cfi_adjust_cfa_offset -8
.cfi_restore r8
.cfi_restore r9
ldrd r6, r7, [sp], #8
.cfi_adjust_cfa_offset -8
.cfi_restore r6
.cfi_restore r7
ldrd r4, r5, [sp], #8
.cfi_adjust_cfa_offset -8
.cfi_restore r4
.cfi_restore r5
pop {r0, pc}
// Put the cfi directives back for the below instructions.
.cfi_adjust_cfa_offset 24
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
.cfi_rel_offset r6, 8
.cfi_rel_offset r7, 12
.cfi_rel_offset r8, 16
.cfi_rel_offset r9, 20
.L_dst_not_word_aligned:
// Align dst to word.
rsb ip, ip, #4
@ -323,12 +315,4 @@
// Src is guaranteed to be at least word aligned by this point.
b .L_word_aligned
// Undo any cfi directives from above.
.cfi_adjust_cfa_offset -24
.cfi_restore r4
.cfi_restore r5
.cfi_restore r6
.cfi_restore r7
.cfi_restore r8
.cfi_restore r9
END(MEMCPY_BASE_ALIGNED)

View File

@ -1,103 +0,0 @@
/*
* Copyright (C) 2008 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.
*/
/*
* Copyright (c) 2013 ARM Ltd
* All rights reserved.
*
* 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. The name of the company may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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 <private/bionic_asm.h>
#include <private/libc_events.h>
.text
.syntax unified
.fpu neon
ENTRY(__memcpy_chk)
cmp r2, r3
bhi .L_memcpy_chk_fail
// Fall through to memcpy...
END(__memcpy_chk)
// Prototype: void *memcpy (void *dst, const void *src, size_t count).
ENTRY(memcpy)
pld [r1, #64]
push {r0, lr}
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
#include MEMCPY_BASE
// Undo the cfi instructions from above.
.cfi_def_cfa_offset 0
.cfi_restore r0
.cfi_restore lr
.L_memcpy_chk_fail:
// Preserve lr for backtrace.
push {lr}
.cfi_adjust_cfa_offset 4
.cfi_rel_offset lr, 0
ldr r0, error_message
ldr r1, error_code
1:
add r0, pc
bl __fortify_chk_fail
error_code:
.word BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+8)
END(memcpy)
.data
error_string:
.string "memcpy: prevented write past end of buffer"

View File

@ -70,7 +70,7 @@
.macro m_scan_byte
ldrb r3, [r0]
cbz r3, .L_strcat_r0_scan_done
cbz r3, strcat_r0_scan_done
add r0, #1
.endm // m_scan_byte
@ -84,10 +84,10 @@ ENTRY(strcat)
// Quick check to see if src is empty.
ldrb r2, [r1]
pld [r1, #0]
cbnz r2, .L_strcat_continue
cbnz r2, strcat_continue
bx lr
.L_strcat_continue:
strcat_continue:
// To speed up really small dst strings, unroll checking the first 4 bytes.
m_push
m_scan_byte
@ -96,102 +96,95 @@ ENTRY(strcat)
m_scan_byte
ands r3, r0, #7
beq .L_strcat_mainloop
beq strcat_mainloop
// Align to a double word (64 bits).
rsb r3, r3, #8
lsls ip, r3, #31
beq .L_strcat_align_to_32
beq strcat_align_to_32
ldrb r5, [r0]
cbz r5, .L_strcat_r0_scan_done
cbz r5, strcat_r0_scan_done
add r0, r0, #1
.L_strcat_align_to_32:
bcc .L_strcat_align_to_64
strcat_align_to_32:
bcc strcat_align_to_64
ldrb r2, [r0]
cbz r2, .L_strcat_r0_scan_done
cbz r2, strcat_r0_scan_done
add r0, r0, #1
ldrb r4, [r0]
cbz r4, .L_strcat_r0_scan_done
cbz r4, strcat_r0_scan_done
add r0, r0, #1
.L_strcat_align_to_64:
strcat_align_to_64:
tst r3, #4
beq .L_strcat_mainloop
beq strcat_mainloop
ldr r3, [r0], #4
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_strcat_zero_in_second_register
b .L_strcat_mainloop
bne strcat_zero_in_second_register
b strcat_mainloop
.L_strcat_r0_scan_done:
strcat_r0_scan_done:
// For short copies, hard-code checking the first 8 bytes since this
// new code doesn't win until after about 8 bytes.
m_copy_byte reg=r2, cmd=cbz, label=.L_strcpy_finish
m_copy_byte reg=r3, cmd=cbz, label=.L_strcpy_finish
m_copy_byte reg=r4, cmd=cbz, label=.L_strcpy_finish
m_copy_byte reg=r5, cmd=cbz, label=.L_strcpy_finish
m_copy_byte reg=r2, cmd=cbz, label=.L_strcpy_finish
m_copy_byte reg=r3, cmd=cbz, label=.L_strcpy_finish
m_copy_byte reg=r4, cmd=cbz, label=.L_strcpy_finish
m_copy_byte reg=r5, cmd=cbnz, label=.L_strcpy_continue
m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r5, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r5, cmd=cbnz, label=strcpy_continue
.L_strcpy_finish:
strcpy_finish:
m_pop
.L_strcpy_continue:
strcpy_continue:
ands r3, r0, #7
beq .L_strcpy_check_src_align
beq strcpy_check_src_align
// Align to a double word (64 bits).
rsb r3, r3, #8
lsls ip, r3, #31
beq .L_strcpy_align_to_32
beq strcpy_align_to_32
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .L_strcpy_complete
cbz r2, strcpy_complete
.L_strcpy_align_to_32:
bcc .L_strcpy_align_to_64
strcpy_align_to_32:
bcc strcpy_align_to_64
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .L_strcpy_complete
cbz r2, strcpy_complete
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .L_strcpy_complete
cbz r2, strcpy_complete
.L_strcpy_align_to_64:
strcpy_align_to_64:
tst r3, #4
beq .L_strcpy_check_src_align
// Read one byte at a time since we don't know the src alignment
// and we don't want to read into a different page.
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .L_strcpy_complete
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .L_strcpy_complete
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .L_strcpy_complete
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .L_strcpy_complete
beq strcpy_check_src_align
ldr r2, [r1], #4
.L_strcpy_check_src_align:
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne strcpy_zero_in_first_register
str r2, [r0], #4
strcpy_check_src_align:
// At this point dst is aligned to a double word, check if src
// is also aligned to a double word.
ands r3, r1, #7
bne .L_strcpy_unaligned_copy
bne strcpy_unaligned_copy
.p2align 2
.L_strcpy_mainloop:
strcpy_mainloop:
ldrd r2, r3, [r1], #8
pld [r1, #64]
@ -199,128 +192,128 @@ ENTRY(strcat)
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .L_strcpy_zero_in_first_register
bne strcpy_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_strcpy_zero_in_second_register
bne strcpy_zero_in_second_register
strd r2, r3, [r0], #8
b .L_strcpy_mainloop
b strcpy_mainloop
.L_strcpy_complete:
strcpy_complete:
m_pop
.L_strcpy_zero_in_first_register:
strcpy_zero_in_first_register:
lsls lr, ip, #17
bne .L_strcpy_copy1byte
bcs .L_strcpy_copy2bytes
bne strcpy_copy1byte
bcs strcpy_copy2bytes
lsls ip, ip, #1
bne .L_strcpy_copy3bytes
bne strcpy_copy3bytes
.L_strcpy_copy4bytes:
strcpy_copy4bytes:
// Copy 4 bytes to the destiniation.
str r2, [r0]
m_pop
.L_strcpy_copy1byte:
strcpy_copy1byte:
strb r2, [r0]
m_pop
.L_strcpy_copy2bytes:
strcpy_copy2bytes:
strh r2, [r0]
m_pop
.L_strcpy_copy3bytes:
strcpy_copy3bytes:
strh r2, [r0], #2
lsr r2, #16
strb r2, [r0]
m_pop
.L_strcpy_zero_in_second_register:
strcpy_zero_in_second_register:
lsls lr, ip, #17
bne .L_strcpy_copy5bytes
bcs .L_strcpy_copy6bytes
bne strcpy_copy5bytes
bcs strcpy_copy6bytes
lsls ip, ip, #1
bne .L_strcpy_copy7bytes
bne strcpy_copy7bytes
// Copy 8 bytes to the destination.
strd r2, r3, [r0]
m_pop
.L_strcpy_copy5bytes:
strcpy_copy5bytes:
str r2, [r0], #4
strb r3, [r0]
m_pop
.L_strcpy_copy6bytes:
strcpy_copy6bytes:
str r2, [r0], #4
strh r3, [r0]
m_pop
.L_strcpy_copy7bytes:
strcpy_copy7bytes:
str r2, [r0], #4
strh r3, [r0], #2
lsr r3, #16
strb r3, [r0]
m_pop
.L_strcpy_unaligned_copy:
strcpy_unaligned_copy:
// Dst is aligned to a double word, while src is at an unknown alignment.
// There are 7 different versions of the unaligned copy code
// to prevent overreading the src. The mainloop of every single version
// will store 64 bits per loop. The difference is how much of src can
// be read without potentially crossing a page boundary.
tbb [pc, r3]
.L_strcpy_unaligned_branchtable:
strcpy_unaligned_branchtable:
.byte 0
.byte ((.L_strcpy_unalign7 - .L_strcpy_unaligned_branchtable)/2)
.byte ((.L_strcpy_unalign6 - .L_strcpy_unaligned_branchtable)/2)
.byte ((.L_strcpy_unalign5 - .L_strcpy_unaligned_branchtable)/2)
.byte ((.L_strcpy_unalign4 - .L_strcpy_unaligned_branchtable)/2)
.byte ((.L_strcpy_unalign3 - .L_strcpy_unaligned_branchtable)/2)
.byte ((.L_strcpy_unalign2 - .L_strcpy_unaligned_branchtable)/2)
.byte ((.L_strcpy_unalign1 - .L_strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign7 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign6 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign5 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign4 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign3 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign2 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign1 - strcpy_unaligned_branchtable)/2)
.p2align 2
// Can read 7 bytes before possibly crossing a page.
.L_strcpy_unalign7:
strcpy_unalign7:
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .L_strcpy_zero_in_first_register
bne strcpy_zero_in_first_register
ldrb r3, [r1]
cbz r3, .L_strcpy_unalign7_copy5bytes
cbz r3, strcpy_unalign7_copy5bytes
ldrb r4, [r1, #1]
cbz r4, .L_strcpy_unalign7_copy6bytes
cbz r4, strcpy_unalign7_copy6bytes
ldrb r5, [r1, #2]
cbz r5, .L_strcpy_unalign7_copy7bytes
cbz r5, strcpy_unalign7_copy7bytes
ldr r3, [r1], #4
pld [r1, #64]
lsrs ip, r3, #24
strd r2, r3, [r0], #8
beq .L_strcpy_unalign_return
b .L_strcpy_unalign7
beq strcpy_unalign_return
b strcpy_unalign7
.L_strcpy_unalign7_copy5bytes:
strcpy_unalign7_copy5bytes:
str r2, [r0], #4
strb r3, [r0]
.L_strcpy_unalign_return:
strcpy_unalign_return:
m_pop
.L_strcpy_unalign7_copy6bytes:
strcpy_unalign7_copy6bytes:
str r2, [r0], #4
strb r3, [r0], #1
strb r4, [r0], #1
m_pop
.L_strcpy_unalign7_copy7bytes:
strcpy_unalign7_copy7bytes:
str r2, [r0], #4
strb r3, [r0], #1
strb r4, [r0], #1
@ -329,41 +322,41 @@ ENTRY(strcat)
.p2align 2
// Can read 6 bytes before possibly crossing a page.
.L_strcpy_unalign6:
strcpy_unalign6:
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .L_strcpy_zero_in_first_register
bne strcpy_zero_in_first_register
ldrb r4, [r1]
cbz r4, .L_strcpy_unalign_copy5bytes
cbz r4, strcpy_unalign_copy5bytes
ldrb r5, [r1, #1]
cbz r5, .L_strcpy_unalign_copy6bytes
cbz r5, strcpy_unalign_copy6bytes
ldr r3, [r1], #4
pld [r1, #64]
tst r3, #0xff0000
beq .L_strcpy_copy7bytes
beq strcpy_copy7bytes
lsrs ip, r3, #24
strd r2, r3, [r0], #8
beq .L_strcpy_unalign_return
b .L_strcpy_unalign6
beq strcpy_unalign_return
b strcpy_unalign6
.p2align 2
// Can read 5 bytes before possibly crossing a page.
.L_strcpy_unalign5:
strcpy_unalign5:
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .L_strcpy_zero_in_first_register
bne strcpy_zero_in_first_register
ldrb r4, [r1]
cbz r4, .L_strcpy_unalign_copy5bytes
cbz r4, strcpy_unalign_copy5bytes
ldr r3, [r1], #4
@ -372,17 +365,17 @@ ENTRY(strcat)
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_strcpy_zero_in_second_register
bne strcpy_zero_in_second_register
strd r2, r3, [r0], #8
b .L_strcpy_unalign5
b strcpy_unalign5
.L_strcpy_unalign_copy5bytes:
strcpy_unalign_copy5bytes:
str r2, [r0], #4
strb r4, [r0]
m_pop
.L_strcpy_unalign_copy6bytes:
strcpy_unalign_copy6bytes:
str r2, [r0], #4
strb r4, [r0], #1
strb r5, [r0]
@ -390,13 +383,13 @@ ENTRY(strcat)
.p2align 2
// Can read 4 bytes before possibly crossing a page.
.L_strcpy_unalign4:
strcpy_unalign4:
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .L_strcpy_zero_in_first_register
bne strcpy_zero_in_first_register
ldr r3, [r1], #4
pld [r1, #64]
@ -404,20 +397,20 @@ ENTRY(strcat)
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_strcpy_zero_in_second_register
bne strcpy_zero_in_second_register
strd r2, r3, [r0], #8
b .L_strcpy_unalign4
b strcpy_unalign4
.p2align 2
// Can read 3 bytes before possibly crossing a page.
.L_strcpy_unalign3:
strcpy_unalign3:
ldrb r2, [r1]
cbz r2, .L_strcpy_unalign3_copy1byte
cbz r2, strcpy_unalign3_copy1byte
ldrb r3, [r1, #1]
cbz r3, .L_strcpy_unalign3_copy2bytes
cbz r3, strcpy_unalign3_copy2bytes
ldrb r4, [r1, #2]
cbz r4, .L_strcpy_unalign3_copy3bytes
cbz r4, strcpy_unalign3_copy3bytes
ldr r2, [r1], #4
ldr r3, [r1], #4
@ -425,26 +418,26 @@ ENTRY(strcat)
pld [r1, #64]
lsrs lr, r2, #24
beq .L_strcpy_copy4bytes
beq strcpy_copy4bytes
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_strcpy_zero_in_second_register
bne strcpy_zero_in_second_register
strd r2, r3, [r0], #8
b .L_strcpy_unalign3
b strcpy_unalign3
.L_strcpy_unalign3_copy1byte:
strcpy_unalign3_copy1byte:
strb r2, [r0]
m_pop
.L_strcpy_unalign3_copy2bytes:
strcpy_unalign3_copy2bytes:
strb r2, [r0], #1
strb r3, [r0]
m_pop
.L_strcpy_unalign3_copy3bytes:
strcpy_unalign3_copy3bytes:
strb r2, [r0], #1
strb r3, [r0], #1
strb r4, [r0]
@ -452,34 +445,34 @@ ENTRY(strcat)
.p2align 2
// Can read 2 bytes before possibly crossing a page.
.L_strcpy_unalign2:
strcpy_unalign2:
ldrb r2, [r1]
cbz r2, .L_strcpy_unalign_copy1byte
cbz r2, strcpy_unalign_copy1byte
ldrb r4, [r1, #1]
cbz r4, .L_strcpy_unalign_copy2bytes
cbz r4, strcpy_unalign_copy2bytes
ldr r2, [r1], #4
ldr r3, [r1], #4
pld [r1, #64]
tst r2, #0xff0000
beq .L_strcpy_copy3bytes
beq strcpy_copy3bytes
lsrs ip, r2, #24
beq .L_strcpy_copy4bytes
beq strcpy_copy4bytes
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_strcpy_zero_in_second_register
bne strcpy_zero_in_second_register
strd r2, r3, [r0], #8
b .L_strcpy_unalign2
b strcpy_unalign2
.p2align 2
// Can read 1 byte before possibly crossing a page.
.L_strcpy_unalign1:
strcpy_unalign1:
ldrb r2, [r1]
cbz r2, .L_strcpy_unalign_copy1byte
cbz r2, strcpy_unalign_copy1byte
ldr r2, [r1], #4
ldr r3, [r1], #4
@ -489,27 +482,27 @@ ENTRY(strcat)
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .L_strcpy_zero_in_first_register
bne strcpy_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_strcpy_zero_in_second_register
bne strcpy_zero_in_second_register
strd r2, r3, [r0], #8
b .L_strcpy_unalign1
b strcpy_unalign1
.L_strcpy_unalign_copy1byte:
strcpy_unalign_copy1byte:
strb r2, [r0]
m_pop
.L_strcpy_unalign_copy2bytes:
strcpy_unalign_copy2bytes:
strb r2, [r0], #1
strb r4, [r0]
m_pop
.p2align 2
.L_strcat_mainloop:
strcat_mainloop:
ldrd r2, r3, [r0], #8
pld [r0, #64]
@ -517,59 +510,59 @@ ENTRY(strcat)
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .L_strcat_zero_in_first_register
bne strcat_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_strcat_zero_in_second_register
b .L_strcat_mainloop
bne strcat_zero_in_second_register
b strcat_mainloop
.L_strcat_zero_in_first_register:
strcat_zero_in_first_register:
// Prefetch the src now, it's going to be used soon.
pld [r1, #0]
lsls lr, ip, #17
bne .L_strcat_sub8
bcs .L_strcat_sub7
bne strcat_sub8
bcs strcat_sub7
lsls ip, ip, #1
bne .L_strcat_sub6
bne strcat_sub6
sub r0, r0, #5
b .L_strcat_r0_scan_done
b strcat_r0_scan_done
.L_strcat_sub8:
strcat_sub8:
sub r0, r0, #8
b .L_strcat_r0_scan_done
b strcat_r0_scan_done
.L_strcat_sub7:
strcat_sub7:
sub r0, r0, #7
b .L_strcat_r0_scan_done
b strcat_r0_scan_done
.L_strcat_sub6:
strcat_sub6:
sub r0, r0, #6
b .L_strcat_r0_scan_done
b strcat_r0_scan_done
.L_strcat_zero_in_second_register:
strcat_zero_in_second_register:
// Prefetch the src now, it's going to be used soon.
pld [r1, #0]
lsls lr, ip, #17
bne .L_strcat_sub4
bcs .L_strcat_sub3
bne strcat_sub4
bcs strcat_sub3
lsls ip, ip, #1
bne .L_strcat_sub2
bne strcat_sub2
sub r0, r0, #1
b .L_strcat_r0_scan_done
b strcat_r0_scan_done
.L_strcat_sub4:
strcat_sub4:
sub r0, r0, #4
b .L_strcat_r0_scan_done
b strcat_r0_scan_done
.L_strcat_sub3:
strcat_sub3:
sub r0, r0, #3
b .L_strcat_r0_scan_done
b strcat_r0_scan_done
.L_strcat_sub2:
strcat_sub2:
sub r0, r0, #2
b .L_strcat_r0_scan_done
b strcat_r0_scan_done
END(strcat)

View File

@ -149,20 +149,13 @@ ENTRY(strcpy)
.Lstringcopy_align_to_64:
tst r3, #4
beq .Lstringcopy_check_src_align
// Read one byte at a time since we don't have any idea about the alignment
// of the source and we don't want to read into a different page.
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .Lstringcopy_complete
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .Lstringcopy_complete
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .Lstringcopy_complete
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .Lstringcopy_complete
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .Lstringcopy_zero_in_first_register
str r2, [r0], #4
.Lstringcopy_check_src_align:
// At this point dst is aligned to a double word, check if src

View File

@ -65,38 +65,38 @@ ENTRY(strlen)
mov r1, r0
ands r3, r0, #7
beq .L_mainloop
beq mainloop
// Align to a double word (64 bits).
rsb r3, r3, #8
lsls ip, r3, #31
beq .L_align_to_32
beq align_to_32
ldrb r2, [r1], #1
cbz r2, .L_update_count_and_return
cbz r2, update_count_and_return
.L_align_to_32:
bcc .L_align_to_64
align_to_32:
bcc align_to_64
ands ip, r3, #2
beq .L_align_to_64
beq align_to_64
ldrb r2, [r1], #1
cbz r2, .L_update_count_and_return
cbz r2, update_count_and_return
ldrb r2, [r1], #1
cbz r2, .L_update_count_and_return
cbz r2, update_count_and_return
.L_align_to_64:
align_to_64:
tst r3, #4
beq .L_mainloop
beq mainloop
ldr r3, [r1], #4
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_zero_in_second_register
bne zero_in_second_register
.p2align 2
.L_mainloop:
mainloop:
ldrd r2, r3, [r1], #8
pld [r1, #64]
@ -104,62 +104,62 @@ ENTRY(strlen)
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .L_zero_in_first_register
bne zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .L_zero_in_second_register
b .L_mainloop
bne zero_in_second_register
b mainloop
.L_update_count_and_return:
update_count_and_return:
sub r0, r1, r0
sub r0, r0, #1
bx lr
.L_zero_in_first_register:
zero_in_first_register:
sub r0, r1, r0
lsls r3, ip, #17
bne .L_sub8_and_return
bcs .L_sub7_and_return
bne sub8_and_return
bcs sub7_and_return
lsls ip, ip, #1
bne .L_sub6_and_return
bne sub6_and_return
sub r0, r0, #5
bx lr
.L_sub8_and_return:
sub8_and_return:
sub r0, r0, #8
bx lr
.L_sub7_and_return:
sub7_and_return:
sub r0, r0, #7
bx lr
.L_sub6_and_return:
sub6_and_return:
sub r0, r0, #6
bx lr
.L_zero_in_second_register:
zero_in_second_register:
sub r0, r1, r0
lsls r3, ip, #17
bne .L_sub4_and_return
bcs .L_sub3_and_return
bne sub4_and_return
bcs sub3_and_return
lsls ip, ip, #1
bne .L_sub2_and_return
bne sub2_and_return
sub r0, r0, #1
bx lr
.L_sub4_and_return:
sub4_and_return:
sub r0, r0, #4
bx lr
.L_sub3_and_return:
sub3_and_return:
sub r0, r0, #3
bx lr
.L_sub2_and_return:
sub2_and_return:
sub r0, r0, #2
bx lr
END(strlen)

View File

@ -1,17 +1,3 @@
libc_openbsd_src_files_exclude_arm += \
upstream-openbsd/lib/libc/string/memmove.c \
upstream-openbsd/lib/libc/string/stpcpy.c \
upstream-openbsd/lib/libc/string/strcat.c \
libc_bionic_src_files_exclude_arm += \
arch-arm/generic/bionic/memcpy.S \
arch-arm/generic/bionic/memset.S \
arch-arm/generic/bionic/strcmp.S \
arch-arm/generic/bionic/strcpy.S \
arch-arm/generic/bionic/strlen.c \
bionic/__strcat_chk.cpp \
bionic/__strcpy_chk.cpp \
libc_bionic_src_files_arm += \
arch-arm/cortex-a15/bionic/memcpy.S \
arch-arm/cortex-a15/bionic/memset.S \
@ -22,6 +8,4 @@ libc_bionic_src_files_arm += \
arch-arm/cortex-a15/bionic/strcpy.S \
arch-arm/cortex-a15/bionic/__strcpy_chk.S \
arch-arm/cortex-a15/bionic/strlen.S \
libc_bionic_src_files_arm += \
arch-arm/denver/bionic/memmove.S \
bionic/memmove.c \

View File

@ -1,32 +0,0 @@
# This file represents the best optimized routines that are the middle
# ground when running on a big/little system that is cortex-a57/cortex-a53.
# The cortex-a7 optimized routines, and the cortex-a53 optimized routines
# decrease performance on cortex-a57 processors by as much as 20%.
libc_openbsd_src_files_exclude_arm += \
upstream-openbsd/lib/libc/string/memmove.c \
upstream-openbsd/lib/libc/string/stpcpy.c \
upstream-openbsd/lib/libc/string/strcat.c \
libc_bionic_src_files_exclude_arm += \
arch-arm/generic/bionic/memcpy.S \
arch-arm/generic/bionic/memset.S \
arch-arm/generic/bionic/strcmp.S \
arch-arm/generic/bionic/strcpy.S \
arch-arm/generic/bionic/strlen.c \
bionic/__strcat_chk.cpp \
bionic/__strcpy_chk.cpp \
libc_bionic_src_files_arm += \
arch-arm/cortex-a15/bionic/memcpy.S \
arch-arm/cortex-a15/bionic/memset.S \
arch-arm/cortex-a15/bionic/stpcpy.S \
arch-arm/cortex-a15/bionic/strcat.S \
arch-arm/cortex-a15/bionic/__strcat_chk.S \
arch-arm/cortex-a15/bionic/strcmp.S \
arch-arm/cortex-a15/bionic/strcpy.S \
arch-arm/cortex-a15/bionic/__strcpy_chk.S \
arch-arm/cortex-a15/bionic/strlen.S \
libc_bionic_src_files_arm += \
arch-arm/denver/bionic/memmove.S \

View File

@ -1,32 +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.
*/
// Indicate which memcpy base file to include.
#define MEMCPY_BASE "arch-arm/cortex-a53/bionic/memcpy_base.S"
#include "arch-arm/cortex-a15/bionic/__strcat_chk_common.S"

View File

@ -1,32 +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.
*/
// Indicate which memcpy base file to include.
#define MEMCPY_BASE "arch-arm/cortex-a53/bionic/memcpy_base.S"
#include "arch-arm/cortex-a15/bionic/__strcpy_chk_common.S"

View File

@ -1,143 +0,0 @@
/*
* Copyright (C) 2008 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.
*/
/*
* Copyright (c) 2013 ARM Ltd
* All rights reserved.
*
* 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. The name of the company may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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.
*/
.L_memcpy_base:
// Assumes that n >= 0, and dst, src are valid pointers.
cmp r2, #16
blo .L_copy_less_than_16_unknown_align
.L_copy_unknown_alignment:
// Unknown alignment of src and dst.
// Assumes that the first few bytes have already been prefetched.
// Align destination to 128 bits. The mainloop store instructions
// require this alignment or they will throw an exception.
rsb r3, r0, #0
ands r3, r3, #0xF
beq 2f
// Copy up to 15 bytes (count in r3).
sub r2, r2, r3
movs ip, r3, lsl #31
itt mi
ldrbmi lr, [r1], #1
strbmi lr, [r0], #1
itttt cs
ldrbcs ip, [r1], #1
ldrbcs lr, [r1], #1
strbcs ip, [r0], #1
strbcs lr, [r0], #1
movs ip, r3, lsl #29
bge 1f
// Copies 4 bytes, dst 32 bits aligned before, at least 64 bits after.
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
1: bcc 2f
// Copies 8 bytes, dst 64 bits aligned before, at least 128 bits after.
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0, :64]!
2: // Make sure we have at least 64 bytes to copy.
subs r2, r2, #64
blo 2f
1: // The main loop copies 64 bytes at a time.
vld1.8 {d0 - d3}, [r1]!
vld1.8 {d4 - d7}, [r1]!
subs r2, r2, #64
vstmia r0!, {d0 - d7}
pld [r1, #(64*10)]
bhs 1b
2: // Fix-up the remaining count and make sure we have >= 32 bytes left.
adds r2, r2, #32
blo 3f
// 32 bytes. These cache lines were already preloaded.
vld1.8 {d0 - d3}, [r1]!
sub r2, r2, #32
vst1.8 {d0 - d3}, [r0, :128]!
3: // Less than 32 left.
add r2, r2, #32
tst r2, #0x10
beq .L_copy_less_than_16_unknown_align
// Copies 16 bytes, destination 128 bits aligned.
vld1.8 {d0, d1}, [r1]!
vst1.8 {d0, d1}, [r0, :128]!
.L_copy_less_than_16_unknown_align:
// Copy up to 15 bytes (count in r2).
movs ip, r2, lsl #29
bcc 1f
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0]!
1: bge 2f
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
2: // Copy 0 to 4 bytes.
lsls r2, r2, #31
itt ne
ldrbne lr, [r1], #1
strbne lr, [r0], #1
itttt cs
ldrbcs ip, [r1], #1
ldrbcs lr, [r1]
strbcs ip, [r0], #1
strbcs lr, [r0]
pop {r0, pc}

View File

@ -1,31 +0,0 @@
libc_openbsd_src_files_exclude_arm += \
upstream-openbsd/lib/libc/string/memmove.c \
upstream-openbsd/lib/libc/string/stpcpy.c \
upstream-openbsd/lib/libc/string/strcat.c \
libc_bionic_src_files_exclude_arm += \
arch-arm/generic/bionic/memcpy.S \
arch-arm/generic/bionic/memset.S \
arch-arm/generic/bionic/strcmp.S \
arch-arm/generic/bionic/strcpy.S \
arch-arm/generic/bionic/strlen.c \
bionic/__strcat_chk.cpp \
bionic/__strcpy_chk.cpp \
libc_bionic_src_files_arm += \
arch-arm/cortex-a53/bionic/memcpy.S \
arch-arm/cortex-a53/bionic/__strcat_chk.S \
arch-arm/cortex-a53/bionic/__strcpy_chk.S \
libc_bionic_src_files_arm += \
arch-arm/cortex-a7/bionic/memset.S \
libc_bionic_src_files_arm += \
arch-arm/cortex-a15/bionic/stpcpy.S \
arch-arm/cortex-a15/bionic/strcat.S \
arch-arm/cortex-a15/bionic/strcmp.S \
arch-arm/cortex-a15/bionic/strcpy.S \
arch-arm/cortex-a15/bionic/strlen.S \
libc_bionic_src_files_arm += \
arch-arm/denver/bionic/memmove.S \

View File

@ -1,180 +0,0 @@
/*
* Copyright (C) 2013 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 <machine/cpu-features.h>
#include <private/bionic_asm.h>
#include <private/libc_events.h>
/*
* Optimized memset() for ARM.
*
* memset() returns its first argument.
*/
.fpu neon
.syntax unified
ENTRY(__memset_chk)
cmp r2, r3
bls .L_done
// Preserve lr for backtrace.
push {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
ldr r0, error_message
ldr r1, error_code
1:
add r0, pc
bl __fortify_chk_fail
error_code:
.word BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+8)
END(__memset_chk)
ENTRY(bzero)
mov r2, r1
mov r1, #0
.L_done:
// Fall through to memset...
END(bzero)
ENTRY(memset)
mov r3, r0
// At this point only d0, d1 are going to be used below.
vdup.8 q0, r1
cmp r2, #16
blo .L_set_less_than_16_unknown_align
.L_check_alignment:
// Align destination to a double word to avoid the store crossing
// a cache line boundary.
ands ip, r3, #7
bne .L_do_double_word_align
.L_double_word_aligned:
// Duplicate since the less than 64 can use d2, d3.
vmov q1, q0
subs r2, #64
blo .L_set_less_than_64
// Duplicate the copy value so that we can store 64 bytes at a time.
vmov q2, q0
vmov q3, q0
1: // Main loop stores 64 bytes at a time.
subs r2, #64
vstmia r3!, {d0 - d7}
bge 1b
.L_set_less_than_64:
// Restore r2 to the count of bytes left to set.
add r2, #64
lsls ip, r2, #27
bcc .L_set_less_than_32
// Set 32 bytes.
vstmia r3!, {d0 - d3}
.L_set_less_than_32:
bpl .L_set_less_than_16
// Set 16 bytes.
vstmia r3!, {d0, d1}
.L_set_less_than_16:
// Less than 16 bytes to set.
lsls ip, r2, #29
bcc .L_set_less_than_8
// Set 8 bytes.
vstmia r3!, {d0}
.L_set_less_than_8:
bpl .L_set_less_than_4
// Set 4 bytes
vst1.32 {d0[0]}, [r3]!
.L_set_less_than_4:
lsls ip, r2, #31
it ne
strbne r1, [r3], #1
itt cs
strbcs r1, [r3], #1
strbcs r1, [r3]
bx lr
.L_do_double_word_align:
rsb ip, ip, #8
sub r2, r2, ip
// Do this comparison now, otherwise we'll need to save a
// register to the stack since we've used all available
// registers.
cmp ip, #4
blo 1f
// Need to do a four byte copy.
movs ip, ip, lsl #31
it mi
strbmi r1, [r3], #1
itt cs
strbcs r1, [r3], #1
strbcs r1, [r3], #1
vst1.32 {d0[0]}, [r3]!
b .L_double_word_aligned
1:
// No four byte copy.
movs ip, ip, lsl #31
it mi
strbmi r1, [r3], #1
itt cs
strbcs r1, [r3], #1
strbcs r1, [r3], #1
b .L_double_word_aligned
.L_set_less_than_16_unknown_align:
// Set up to 15 bytes.
movs ip, r2, lsl #29
bcc 1f
vst1.8 {d0}, [r3]!
1: bge 2f
vst1.32 {d0[0]}, [r3]!
2: movs ip, r2, lsl #31
it mi
strbmi r1, [r3], #1
itt cs
strbcs r1, [r3], #1
strbcs r1, [r3], #1
bx lr
END(memset)
.data
error_string:
.string "memset: prevented write past end of buffer"

View File

@ -1,29 +1 @@
libc_openbsd_src_files_exclude_arm += \
upstream-openbsd/lib/libc/string/memmove.c \
upstream-openbsd/lib/libc/string/stpcpy.c \
upstream-openbsd/lib/libc/string/strcat.c \
libc_bionic_src_files_exclude_arm += \
arch-arm/generic/bionic/memcpy.S \
arch-arm/generic/bionic/memset.S \
arch-arm/generic/bionic/strcmp.S \
arch-arm/generic/bionic/strcpy.S \
arch-arm/generic/bionic/strlen.c \
bionic/__strcat_chk.cpp \
bionic/__strcpy_chk.cpp \
libc_bionic_src_files_arm += \
arch-arm/cortex-a7/bionic/memset.S \
libc_bionic_src_files_arm += \
arch-arm/cortex-a15/bionic/memcpy.S \
arch-arm/cortex-a15/bionic/stpcpy.S \
arch-arm/cortex-a15/bionic/strcat.S \
arch-arm/cortex-a15/bionic/__strcat_chk.S \
arch-arm/cortex-a15/bionic/strcmp.S \
arch-arm/cortex-a15/bionic/strcpy.S \
arch-arm/cortex-a15/bionic/__strcpy_chk.S \
arch-arm/cortex-a15/bionic/strlen.S \
libc_bionic_src_files_arm += \
arch-arm/denver/bionic/memmove.S \
include bionic/libc/arch-arm/cortex-a15/cortex-a15.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
@ -133,7 +133,8 @@ ENTRY_PRIVATE(MEMCPY_BASE)
strbcs ip, [r0], #1
strbcs lr, [r0], #1
ldmfd sp!, {r0, pc}
ldmfd sp!, {r0, lr}
bx lr
END(MEMCPY_BASE)
ENTRY_PRIVATE(MEMCPY_BASE_ALIGNED)

View File

@ -35,7 +35,6 @@
*/
.fpu neon
.syntax unified
ENTRY(__memset_chk)
cmp r2, r3
@ -69,9 +68,12 @@ END(bzero)
ENTRY(memset)
// The neon memset only wins for less than 132.
cmp r2, #132
bhi .L_memset_large_copy
bhi __memset_large_copy
stmfd sp!, {r0}
.cfi_def_cfa_offset 4
.cfi_rel_offset r0, 0
mov r3, r0
vdup.8 q0, r1
/* make sure we have at least 32 bytes to write */
@ -81,7 +83,7 @@ ENTRY(memset)
1: /* The main loop writes 32 bytes at a time */
subs r2, r2, #32
vst1.8 {d0 - d3}, [r3]!
vst1.8 {d0 - d3}, [r0]!
bhs 1b
2: /* less than 32 left */
@ -90,20 +92,22 @@ ENTRY(memset)
beq 3f
// writes 16 bytes, 128-bits aligned
vst1.8 {d0, d1}, [r3]!
vst1.8 {d0, d1}, [r0]!
3: /* write up to 15-bytes (count in r2) */
movs ip, r2, lsl #29
bcc 1f
vst1.8 {d0}, [r3]!
vst1.8 {d0}, [r0]!
1: bge 2f
vst1.32 {d0[0]}, [r3]!
vst1.32 {d0[0]}, [r0]!
2: movs ip, r2, lsl #31
strbmi r1, [r3], #1
strbcs r1, [r3], #1
strbcs r1, [r3], #1
strmib r1, [r0], #1
strcsb r1, [r0], #1
strcsb r1, [r0], #1
ldmfd sp!, {r0}
bx lr
END(memset)
.L_memset_large_copy:
ENTRY_PRIVATE(__memset_large_copy)
/* compute the offset to align the destination
* offset = (4-(src&3))&3 = -src & 3
*/
@ -127,11 +131,12 @@ ENTRY(memset)
orr r1, r1, r1, lsr #16
movs r12, r3, lsl #31
strbcs r1, [r0], #1 /* can't use strh (alignment unknown) */
strbcs r1, [r0], #1
strbmi r1, [r0], #1
strcsb r1, [r0], #1 /* can't use strh (alignment unknown) */
strcsb r1, [r0], #1
strmib r1, [r0], #1
subs r2, r2, r3
popls {r0, r4-r7, pc} /* return */
ldmlsfd sp!, {r0, r4-r7, lr} /* return */
bxls lr
/* align the destination to a cache-line */
mov r12, r1
@ -150,9 +155,9 @@ ENTRY(memset)
/* conditionally writes 0 to 7 words (length in r3) */
movs r3, r3, lsl #28
stmcs r0!, {r1, lr}
stmcs r0!, {r1, lr}
stmmi r0!, {r1, lr}
stmcsia r0!, {r1, lr}
stmcsia r0!, {r1, lr}
stmmiia r0!, {r1, lr}
movs r3, r3, lsl #2
strcs r1, [r0], #4
@ -167,15 +172,16 @@ ENTRY(memset)
/* conditionally stores 0 to 31 bytes */
movs r2, r2, lsl #28
stmcs r0!, {r1,r3,r12,lr}
stmmi r0!, {r1, lr}
stmcsia r0!, {r1,r3,r12,lr}
stmmiia r0!, {r1, lr}
movs r2, r2, lsl #2
strcs r1, [r0], #4
strhmi r1, [r0], #2
strmih r1, [r0], #2
movs r2, r2, lsl #2
strbcs r1, [r0]
ldmfd sp!, {r0, r4-r7, pc}
END(memset)
strcsb r1, [r0]
ldmfd sp!, {r0, r4-r7, lr}
bx lr
END(__memset_large_copy)
.data
error_string:

View File

@ -70,7 +70,7 @@
.macro m_scan_byte
ldrb r3, [r0]
cbz r3, .Lstrcat_r0_scan_done
cbz r3, strcat_r0_scan_done
add r0, #1
.endm // m_scan_byte
@ -84,10 +84,10 @@ ENTRY(strcat)
// Quick check to see if src is empty.
ldrb r2, [r1]
pld [r1, #0]
cbnz r2, .Lstrcat_continue
cbnz r2, strcat_continue
bx lr
.Lstrcat_continue:
strcat_continue:
// To speed up really small dst strings, unroll checking the first 4 bytes.
m_push
m_scan_byte
@ -96,10 +96,10 @@ ENTRY(strcat)
m_scan_byte
ands r3, r0, #7
bne .Lstrcat_align_src
bne strcat_align_src
.p2align 2
.Lstrcat_mainloop:
strcat_mainloop:
ldmia r0!, {r2, r3}
pld [r0, #64]
@ -107,28 +107,28 @@ ENTRY(strcat)
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .Lstrcat_zero_in_first_register
bne strcat_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .Lstrcat_zero_in_second_register
b .Lstrcat_mainloop
bne strcat_zero_in_second_register
b strcat_mainloop
.Lstrcat_zero_in_first_register:
strcat_zero_in_first_register:
sub r0, r0, #4
.Lstrcat_zero_in_second_register:
strcat_zero_in_second_register:
// Check for zero in byte 0.
tst ip, #0x80
it ne
subne r0, r0, #4
bne .Lstrcat_r0_scan_done
bne strcat_r0_scan_done
// Check for zero in byte 1.
tst ip, #0x8000
it ne
subne r0, r0, #3
bne .Lstrcat_r0_scan_done
bne strcat_r0_scan_done
// Check for zero in byte 2.
tst ip, #0x800000
it ne
@ -137,33 +137,33 @@ ENTRY(strcat)
// Zero is in byte 3.
subeq r0, r0, #1
.Lstrcat_r0_scan_done:
strcat_r0_scan_done:
// Unroll the first 8 bytes that will be copied.
m_copy_byte reg=r2, cmd=cbz, label=.Lstrcpy_finish
m_copy_byte reg=r3, cmd=cbz, label=.Lstrcpy_finish
m_copy_byte reg=r4, cmd=cbz, label=.Lstrcpy_finish
m_copy_byte reg=r5, cmd=cbz, label=.Lstrcpy_finish
m_copy_byte reg=r2, cmd=cbz, label=.Lstrcpy_finish
m_copy_byte reg=r3, cmd=cbz, label=.Lstrcpy_finish
m_copy_byte reg=r4, cmd=cbz, label=.Lstrcpy_finish
m_copy_byte reg=r5, cmd=cbnz, label=.Lstrcpy_continue
m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r5, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r5, cmd=cbnz, label=strcpy_continue
.Lstrcpy_finish:
strcpy_finish:
m_ret inst=pop
.Lstrcpy_continue:
strcpy_continue:
pld [r1, #0]
ands r3, r0, #7
bne .Lstrcpy_align_dst
bne strcpy_align_dst
.Lstrcpy_check_src_align:
strcpy_check_src_align:
// At this point dst is aligned to a double word, check if src
// is also aligned to a double word.
ands r3, r1, #7
bne .Lstrcpy_unaligned_copy
bne strcpy_unaligned_copy
.p2align 2
.Lstrcpy_mainloop:
strcpy_mainloop:
ldmia r1!, {r2, r3}
pld [r1, #64]
@ -171,17 +171,17 @@ ENTRY(strcat)
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .Lstrcpy_zero_in_first_register
bne strcpy_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .Lstrcpy_zero_in_second_register
bne strcpy_zero_in_second_register
stmia r0!, {r2, r3}
b .Lstrcpy_mainloop
b strcpy_mainloop
.Lstrcpy_zero_in_first_register:
strcpy_zero_in_first_register:
lsls lr, ip, #17
itt ne
strbne r2, [r0]
@ -198,7 +198,7 @@ ENTRY(strcat)
strb r3, [r0]
m_ret inst=pop
.Lstrcpy_zero_in_second_register:
strcpy_zero_in_second_register:
lsls lr, ip, #17
ittt ne
stmiane r0!, {r2}
@ -218,18 +218,18 @@ ENTRY(strcat)
strb r4, [r0]
m_ret inst=pop
.Lstrcpy_align_dst:
strcpy_align_dst:
// Align to a double word (64 bits).
rsb r3, r3, #8
lsls ip, r3, #31
beq .Lstrcpy_align_to_32
beq strcpy_align_to_32
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .Lstrcpy_complete
cbz r2, strcpy_complete
.Lstrcpy_align_to_32:
bcc .Lstrcpy_align_to_64
strcpy_align_to_32:
bcc strcpy_align_to_64
ldrb r4, [r1], #1
strb r4, [r0], #1
@ -242,83 +242,76 @@ ENTRY(strcat)
it eq
m_ret inst=popeq
.Lstrcpy_align_to_64:
strcpy_align_to_64:
tst r3, #4
beq .Lstrcpy_check_src_align
// Read one byte at a time since we don't know the src alignment
// and we don't want to read into a different page.
ldrb r4, [r1], #1
strb r4, [r0], #1
cbz r4, .Lstrcpy_complete
ldrb r5, [r1], #1
strb r5, [r0], #1
cbz r5, .Lstrcpy_complete
ldrb r4, [r1], #1
strb r4, [r0], #1
cbz r4, .Lstrcpy_complete
ldrb r5, [r1], #1
strb r5, [r0], #1
cbz r5, .Lstrcpy_complete
b .Lstrcpy_check_src_align
beq strcpy_check_src_align
ldr r2, [r1], #4
.Lstrcpy_complete:
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne strcpy_zero_in_first_register
stmia r0!, {r2}
b strcpy_check_src_align
strcpy_complete:
m_ret inst=pop
.Lstrcpy_unaligned_copy:
strcpy_unaligned_copy:
// Dst is aligned to a double word, while src is at an unknown alignment.
// There are 7 different versions of the unaligned copy code
// to prevent overreading the src. The mainloop of every single version
// will store 64 bits per loop. The difference is how much of src can
// be read without potentially crossing a page boundary.
tbb [pc, r3]
.Lstrcpy_unaligned_branchtable:
strcpy_unaligned_branchtable:
.byte 0
.byte ((.Lstrcpy_unalign7 - .Lstrcpy_unaligned_branchtable)/2)
.byte ((.Lstrcpy_unalign6 - .Lstrcpy_unaligned_branchtable)/2)
.byte ((.Lstrcpy_unalign5 - .Lstrcpy_unaligned_branchtable)/2)
.byte ((.Lstrcpy_unalign4 - .Lstrcpy_unaligned_branchtable)/2)
.byte ((.Lstrcpy_unalign3 - .Lstrcpy_unaligned_branchtable)/2)
.byte ((.Lstrcpy_unalign2 - .Lstrcpy_unaligned_branchtable)/2)
.byte ((.Lstrcpy_unalign1 - .Lstrcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign7 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign6 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign5 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign4 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign3 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign2 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign1 - strcpy_unaligned_branchtable)/2)
.p2align 2
// Can read 7 bytes before possibly crossing a page.
.Lstrcpy_unalign7:
strcpy_unalign7:
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .Lstrcpy_zero_in_first_register
bne strcpy_zero_in_first_register
ldrb r3, [r1]
cbz r3, .Lstrcpy_unalign7_copy5bytes
cbz r3, strcpy_unalign7_copy5bytes
ldrb r4, [r1, #1]
cbz r4, .Lstrcpy_unalign7_copy6bytes
cbz r4, strcpy_unalign7_copy6bytes
ldrb r5, [r1, #2]
cbz r5, .Lstrcpy_unalign7_copy7bytes
cbz r5, strcpy_unalign7_copy7bytes
ldr r3, [r1], #4
pld [r1, #64]
lsrs ip, r3, #24
stmia r0!, {r2, r3}
beq .Lstrcpy_unalign_return
b .Lstrcpy_unalign7
beq strcpy_unalign_return
b strcpy_unalign7
.Lstrcpy_unalign7_copy5bytes:
strcpy_unalign7_copy5bytes:
stmia r0!, {r2}
strb r3, [r0]
.Lstrcpy_unalign_return:
strcpy_unalign_return:
m_ret inst=pop
.Lstrcpy_unalign7_copy6bytes:
strcpy_unalign7_copy6bytes:
stmia r0!, {r2}
strb r3, [r0], #1
strb r4, [r0], #1
m_ret inst=pop
.Lstrcpy_unalign7_copy7bytes:
strcpy_unalign7_copy7bytes:
stmia r0!, {r2}
strb r3, [r0], #1
strb r4, [r0], #1
@ -327,30 +320,30 @@ ENTRY(strcat)
.p2align 2
// Can read 6 bytes before possibly crossing a page.
.Lstrcpy_unalign6:
strcpy_unalign6:
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .Lstrcpy_zero_in_first_register
bne strcpy_zero_in_first_register
ldrb r4, [r1]
cbz r4, .Lstrcpy_unalign_copy5bytes
cbz r4, strcpy_unalign_copy5bytes
ldrb r5, [r1, #1]
cbz r5, .Lstrcpy_unalign_copy6bytes
cbz r5, strcpy_unalign_copy6bytes
ldr r3, [r1], #4
pld [r1, #64]
tst r3, #0xff0000
beq .Lstrcpy_unalign6_copy7bytes
beq strcpy_unalign6_copy7bytes
lsrs ip, r3, #24
stmia r0!, {r2, r3}
beq .Lstrcpy_unalign_return
b .Lstrcpy_unalign6
beq strcpy_unalign_return
b strcpy_unalign6
.Lstrcpy_unalign6_copy7bytes:
strcpy_unalign6_copy7bytes:
stmia r0!, {r2}
strh r3, [r0], #2
lsr r3, #16
@ -359,16 +352,16 @@ ENTRY(strcat)
.p2align 2
// Can read 5 bytes before possibly crossing a page.
.Lstrcpy_unalign5:
strcpy_unalign5:
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .Lstrcpy_zero_in_first_register
bne strcpy_zero_in_first_register
ldrb r4, [r1]
cbz r4, .Lstrcpy_unalign_copy5bytes
cbz r4, strcpy_unalign_copy5bytes
ldr r3, [r1], #4
@ -377,17 +370,17 @@ ENTRY(strcat)
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .Lstrcpy_zero_in_second_register
bne strcpy_zero_in_second_register
stmia r0!, {r2, r3}
b .Lstrcpy_unalign5
b strcpy_unalign5
.Lstrcpy_unalign_copy5bytes:
strcpy_unalign_copy5bytes:
stmia r0!, {r2}
strb r4, [r0]
m_ret inst=pop
.Lstrcpy_unalign_copy6bytes:
strcpy_unalign_copy6bytes:
stmia r0!, {r2}
strb r4, [r0], #1
strb r5, [r0]
@ -395,13 +388,13 @@ ENTRY(strcat)
.p2align 2
// Can read 4 bytes before possibly crossing a page.
.Lstrcpy_unalign4:
strcpy_unalign4:
ldmia r1!, {r2}
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .Lstrcpy_zero_in_first_register
bne strcpy_zero_in_first_register
ldmia r1!, {r3}
pld [r1, #64]
@ -409,20 +402,20 @@ ENTRY(strcat)
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .Lstrcpy_zero_in_second_register
bne strcpy_zero_in_second_register
stmia r0!, {r2, r3}
b .Lstrcpy_unalign4
b strcpy_unalign4
.p2align 2
// Can read 3 bytes before possibly crossing a page.
.Lstrcpy_unalign3:
strcpy_unalign3:
ldrb r2, [r1]
cbz r2, .Lstrcpy_unalign3_copy1byte
cbz r2, strcpy_unalign3_copy1byte
ldrb r3, [r1, #1]
cbz r3, .Lstrcpy_unalign3_copy2bytes
cbz r3, strcpy_unalign3_copy2bytes
ldrb r4, [r1, #2]
cbz r4, .Lstrcpy_unalign3_copy3bytes
cbz r4, strcpy_unalign3_copy3bytes
ldr r2, [r1], #4
ldr r3, [r1], #4
@ -430,26 +423,26 @@ ENTRY(strcat)
pld [r1, #64]
lsrs lr, r2, #24
beq .Lstrcpy_unalign_copy4bytes
beq strcpy_unalign_copy4bytes
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .Lstrcpy_zero_in_second_register
bne strcpy_zero_in_second_register
stmia r0!, {r2, r3}
b .Lstrcpy_unalign3
b strcpy_unalign3
.Lstrcpy_unalign3_copy1byte:
strcpy_unalign3_copy1byte:
strb r2, [r0]
m_ret inst=pop
.Lstrcpy_unalign3_copy2bytes:
strcpy_unalign3_copy2bytes:
strb r2, [r0], #1
strb r3, [r0]
m_ret inst=pop
.Lstrcpy_unalign3_copy3bytes:
strcpy_unalign3_copy3bytes:
strb r2, [r0], #1
strb r3, [r0], #1
strb r4, [r0]
@ -457,34 +450,34 @@ ENTRY(strcat)
.p2align 2
// Can read 2 bytes before possibly crossing a page.
.Lstrcpy_unalign2:
strcpy_unalign2:
ldrb r2, [r1]
cbz r2, .Lstrcpy_unalign_copy1byte
cbz r2, strcpy_unalign_copy1byte
ldrb r3, [r1, #1]
cbz r3, .Lstrcpy_unalign_copy2bytes
cbz r3, strcpy_unalign_copy2bytes
ldr r2, [r1], #4
ldr r3, [r1], #4
pld [r1, #64]
tst r2, #0xff0000
beq .Lstrcpy_unalign_copy3bytes
beq strcpy_unalign_copy3bytes
lsrs ip, r2, #24
beq .Lstrcpy_unalign_copy4bytes
beq strcpy_unalign_copy4bytes
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .Lstrcpy_zero_in_second_register
bne strcpy_zero_in_second_register
stmia r0!, {r2, r3}
b .Lstrcpy_unalign2
b strcpy_unalign2
.p2align 2
// Can read 1 byte before possibly crossing a page.
.Lstrcpy_unalign1:
strcpy_unalign1:
ldrb r2, [r1]
cbz r2, .Lstrcpy_unalign_copy1byte
cbz r2, strcpy_unalign_copy1byte
ldr r2, [r1], #4
ldr r3, [r1], #4
@ -494,62 +487,62 @@ ENTRY(strcat)
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .Lstrcpy_zero_in_first_register
bne strcpy_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .Lstrcpy_zero_in_second_register
bne strcpy_zero_in_second_register
stmia r0!, {r2, r3}
b .Lstrcpy_unalign1
b strcpy_unalign1
.Lstrcpy_unalign_copy1byte:
strcpy_unalign_copy1byte:
strb r2, [r0]
m_ret inst=pop
.Lstrcpy_unalign_copy2bytes:
strcpy_unalign_copy2bytes:
strb r2, [r0], #1
strb r3, [r0]
m_ret inst=pop
.Lstrcpy_unalign_copy3bytes:
strcpy_unalign_copy3bytes:
strh r2, [r0], #2
lsr r2, #16
strb r2, [r0]
m_ret inst=pop
.Lstrcpy_unalign_copy4bytes:
strcpy_unalign_copy4bytes:
stmia r0, {r2}
m_ret inst=pop
.Lstrcat_align_src:
strcat_align_src:
// Align to a double word (64 bits).
rsb r3, r3, #8
lsls ip, r3, #31
beq .Lstrcat_align_to_32
beq strcat_align_to_32
ldrb r2, [r0], #1
cbz r2, .Lstrcat_r0_update
cbz r2, strcat_r0_update
.Lstrcat_align_to_32:
bcc .Lstrcat_align_to_64
strcat_align_to_32:
bcc strcat_align_to_64
ldrb r2, [r0], #1
cbz r2, .Lstrcat_r0_update
cbz r2, strcat_r0_update
ldrb r2, [r0], #1
cbz r2, .Lstrcat_r0_update
cbz r2, strcat_r0_update
.Lstrcat_align_to_64:
strcat_align_to_64:
tst r3, #4
beq .Lstrcat_mainloop
beq strcat_mainloop
ldr r3, [r0], #4
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne .Lstrcat_zero_in_second_register
b .Lstrcat_mainloop
bne strcat_zero_in_second_register
b strcat_mainloop
.Lstrcat_r0_update:
strcat_r0_update:
sub r0, r0, #1
b .Lstrcat_r0_scan_done
b strcat_r0_scan_done
END(strcat)

View File

@ -244,20 +244,13 @@ ENTRY(strcpy)
.Lstringcopy_align_to_64:
tst r3, #4
beq .Lstringcopy_check_src_align
// Read one byte at a time since we don't have any idea about the alignment
// of the source and we don't want to read into a different page.
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .Lstringcopy_complete
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .Lstringcopy_complete
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .Lstringcopy_complete
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, .Lstringcopy_complete
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne .Lstringcopy_zero_in_first_register
stmia r0!, {r2}
b .Lstringcopy_check_src_align
.Lstringcopy_complete:

View File

@ -1,18 +1,3 @@
libc_openbsd_src_files_exclude_arm += \
upstream-openbsd/lib/libc/string/memmove.c \
upstream-openbsd/lib/libc/string/stpcpy.c \
upstream-openbsd/lib/libc/string/strcat.c \
upstream-openbsd/lib/libc/string/strcpy.c \
libc_bionic_src_files_exclude_arm += \
arch-arm/generic/bionic/memcpy.S \
arch-arm/generic/bionic/memset.S \
arch-arm/generic/bionic/strcmp.S \
arch-arm/generic/bionic/strcpy.S \
arch-arm/generic/bionic/strlen.c \
bionic/__strcat_chk.cpp \
bionic/__strcpy_chk.cpp \
libc_bionic_src_files_arm += \
arch-arm/cortex-a9/bionic/memcpy.S \
arch-arm/cortex-a9/bionic/memset.S \
@ -23,6 +8,4 @@ libc_bionic_src_files_arm += \
arch-arm/cortex-a9/bionic/strcpy.S \
arch-arm/cortex-a9/bionic/__strcpy_chk.S \
arch-arm/cortex-a9/bionic/strlen.S \
libc_bionic_src_files_arm += \
arch-arm/denver/bionic/memmove.S \
bionic/memmove.c \

View File

@ -37,7 +37,6 @@
* memset() returns its first argument.
*/
.cpu cortex-a15
.fpu neon
.syntax unified

View File

@ -1,17 +1,3 @@
libc_openbsd_src_files_exclude_arm += \
upstream-openbsd/lib/libc/string/memmove.c \
upstream-openbsd/lib/libc/string/stpcpy.c \
upstream-openbsd/lib/libc/string/strcat.c \
libc_bionic_src_files_exclude_arm += \
arch-arm/generic/bionic/memcpy.S \
arch-arm/generic/bionic/memset.S \
arch-arm/generic/bionic/strcmp.S \
arch-arm/generic/bionic/strcpy.S \
arch-arm/generic/bionic/strlen.c \
bionic/__strcat_chk.cpp \
bionic/__strcpy_chk.cpp \
libc_bionic_src_files_arm += \
arch-arm/denver/bionic/memcpy.S \
arch-arm/denver/bionic/memmove.S \

View File

@ -37,8 +37,6 @@
* so we have to preserve R0.
*/
.syntax unified
ENTRY(__memcpy_chk)
cmp r2, r3
bhi __memcpy_chk_fail
@ -83,12 +81,12 @@ ENTRY(memcpy)
*/
movs r12, r3, lsl #31
sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */
ldrbmi r3, [r1], #1
ldrbcs r4, [r1], #1
ldrbcs r12,[r1], #1
strbmi r3, [r0], #1
strbcs r4, [r0], #1
strbcs r12,[r0], #1
ldrmib r3, [r1], #1
ldrcsb r4, [r1], #1
ldrcsb r12,[r1], #1
strmib r3, [r0], #1
strcsb r4, [r0], #1
strcsb r12,[r0], #1
.Lsrc_aligned:
@ -111,10 +109,10 @@ ENTRY(memcpy)
/* conditionally copies 0 to 7 words (length in r3) */
movs r12, r3, lsl #28
ldmcs r1!, {r4, r5, r6, r7} /* 16 bytes */
ldmmi r1!, {r8, r9} /* 8 bytes */
stmcs r0!, {r4, r5, r6, r7}
stmmi r0!, {r8, r9}
ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */
ldmmiia r1!, {r8, r9} /* 8 bytes */
stmcsia r0!, {r4, r5, r6, r7}
stmmiia r0!, {r8, r9}
tst r3, #0x4
ldrne r10,[r1], #4 /* 4 bytes */
strne r10,[r0], #4
@ -179,22 +177,23 @@ ENTRY(memcpy)
/* conditionnaly copies 0 to 31 bytes */
movs r12, r2, lsl #28
ldmcs r1!, {r4, r5, r6, r7} /* 16 bytes */
ldmmi r1!, {r8, r9} /* 8 bytes */
stmcs r0!, {r4, r5, r6, r7}
stmmi r0!, {r8, r9}
ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */
ldmmiia r1!, {r8, r9} /* 8 bytes */
stmcsia r0!, {r4, r5, r6, r7}
stmmiia r0!, {r8, r9}
movs r12, r2, lsl #30
ldrcs r3, [r1], #4 /* 4 bytes */
ldrhmi r4, [r1], #2 /* 2 bytes */
ldrmih r4, [r1], #2 /* 2 bytes */
strcs r3, [r0], #4
strhmi r4, [r0], #2
strmih r4, [r0], #2
tst r2, #0x1
ldrbne r3, [r1] /* last byte */
strbne r3, [r0]
ldrneb r3, [r1] /* last byte */
strneb r3, [r0]
/* we're done! restore everything and return */
1: ldmfd sp!, {r5-r11}
ldmfd sp!, {r0, r4, pc}
ldmfd sp!, {r0, r4, lr}
bx lr
/********************************************************************/
@ -229,11 +228,11 @@ ENTRY(memcpy)
* becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
*/
movs r5, r5, lsl #31
strbmi r3, [r0], #1
strmib r3, [r0], #1
movmi r3, r3, lsr #8
strbcs r3, [r0], #1
strcsb r3, [r0], #1
movcs r3, r3, lsr #8
strbcs r3, [r0], #1
strcsb r3, [r0], #1
movcs r3, r3, lsr #8
cmp r2, #4
@ -364,27 +363,28 @@ ENTRY(memcpy)
.Lpartial_word_tail:
/* we have a partial word in the input buffer */
movs r5, lr, lsl #(31-3)
strbmi r3, [r0], #1
strmib r3, [r0], #1
movmi r3, r3, lsr #8
strbcs r3, [r0], #1
strcsb r3, [r0], #1
movcs r3, r3, lsr #8
strbcs r3, [r0], #1
strcsb r3, [r0], #1
/* Refill spilled registers from the stack. Don't update sp. */
ldmfd sp, {r5-r11}
.Lcopy_last_3_and_return:
movs r2, r2, lsl #31 /* copy remaining 0, 1, 2 or 3 bytes */
ldrbmi r2, [r1], #1
ldrbcs r3, [r1], #1
ldrbcs r12,[r1]
strbmi r2, [r0], #1
strbcs r3, [r0], #1
strbcs r12,[r0]
ldrmib r2, [r1], #1
ldrcsb r3, [r1], #1
ldrcsb r12,[r1]
strmib r2, [r0], #1
strcsb r3, [r0], #1
strcsb r12,[r0]
/* we're done! restore sp and spilled registers and return */
add sp, sp, #28
ldmfd sp!, {r0, r4, pc}
ldmfd sp!, {r0, r4, lr}
bx lr
END(memcpy)
// Only reached when the __memcpy_chk check fails.

View File

@ -35,8 +35,6 @@
* memset() returns its first argument.
*/
.syntax unified
ENTRY(__memset_chk)
cmp r2, r3
bls done
@ -78,11 +76,12 @@ ENTRY(memset)
orr r1, r1, r1, lsr #16
movs r12, r3, lsl #31
strbcs r1, [r0], #1 /* can't use strh (alignment unknown) */
strbcs r1, [r0], #1
strbmi r1, [r0], #1
strcsb r1, [r0], #1 /* can't use strh (alignment unknown) */
strcsb r1, [r0], #1
strmib r1, [r0], #1
subs r2, r2, r3
popls {r0, r4-r7, pc} /* return */
ldmlsfd sp!, {r0, r4-r7, lr} /* return */
bxls lr
/* align the destination to a cache-line */
mov r12, r1
@ -101,9 +100,9 @@ ENTRY(memset)
/* conditionally writes 0 to 7 words (length in r3) */
movs r3, r3, lsl #28
stmcs r0!, {r1, lr}
stmcs r0!, {r1, lr}
stmmi r0!, {r1, lr}
stmcsia r0!, {r1, lr}
stmcsia r0!, {r1, lr}
stmmiia r0!, {r1, lr}
movs r3, r3, lsl #2
strcs r1, [r0], #4
@ -118,14 +117,15 @@ ENTRY(memset)
/* conditionally stores 0 to 31 bytes */
movs r2, r2, lsl #28
stmcs r0!, {r1,r3,r12,lr}
stmmi r0!, {r1, lr}
stmcsia r0!, {r1,r3,r12,lr}
stmmiia r0!, {r1, lr}
movs r2, r2, lsl #2
strcs r1, [r0], #4
strhmi r1, [r0], #2
strmih r1, [r0], #2
movs r2, r2, lsl #2
strbcs r1, [r0]
ldmfd sp!, {r0, r4-r7, pc}
strcsb r1, [r0]
ldmfd sp!, {r0, r4-r7, lr}
bx lr
END(memset)
.data

View File

@ -32,8 +32,6 @@
#include <machine/cpu-features.h>
#include <private/bionic_asm.h>
.syntax unified
ENTRY(strcpy)
pld [r1, #0]
eor r2, r0, r1
@ -110,15 +108,15 @@ ENTRY(strcpy)
#ifdef __ARMEB__
tst r2, #0xff00
iteet ne
strhne r2, [ip], #2
strneh r2, [ip], #2
lsreq r2, r2, #8
strbeq r2, [ip]
streqb r2, [ip]
tstne r2, #0xff
#else
tst r2, #0xff
itet ne
strhne r2, [ip], #2
strbeq r2, [ip]
strneh r2, [ip], #2
streqb r2, [ip]
tstne r2, #0xff00
#endif
bne 5b

View File

@ -0,0 +1,11 @@
libc_bionic_src_files_arm += \
arch-arm/generic/bionic/memcpy.S \
arch-arm/generic/bionic/memset.S \
arch-arm/generic/bionic/strcmp.S \
arch-arm/generic/bionic/strcpy.S \
arch-arm/generic/bionic/strlen.c \
bionic/memmove.c \
bionic/__strcat_chk.cpp \
bionic/__strcpy_chk.cpp \
upstream-openbsd/lib/libc/string/stpcpy.c \
upstream-openbsd/lib/libc/string/strcat.c \

View File

@ -38,7 +38,9 @@
#ifndef _ARM32_ASM_H_
#define _ARM32_ASM_H_
#define __bionic_asm_align 0
#ifndef _ALIGN_TEXT
# define _ALIGN_TEXT .align 0
#endif
#undef __bionic_asm_custom_entry
#undef __bionic_asm_custom_end
@ -48,4 +50,10 @@
#undef __bionic_asm_function_type
#define __bionic_asm_function_type #function
#if defined(__ELF__) && defined(PIC)
#define PIC_SYM(x,y) x ## ( ## y ## )
#else
#define PIC_SYM(x,y) x
#endif
#endif /* !_ARM_ASM_H_ */

View File

@ -28,6 +28,14 @@
#ifndef _ARM_MACHINE_CPU_FEATURES_H
#define _ARM_MACHINE_CPU_FEATURES_H
/* The purpose of this file is to define several macros corresponding
* to CPU features that may or may not be available at build time on
* on the target CPU.
*
* This is done to abstract us from the various ARM Architecture
* quirks and alphabet soup.
*/
/* __ARM_ARCH__ is a number corresponding to the ARM revision
* we're going to support. Our toolchain doesn't define __ARM_ARCH__
* so try to guess it.
@ -45,4 +53,31 @@
# endif
#endif
/* define __ARM_HAVE_HALFWORD_MULTIPLY when half-word multiply instructions
* this means variants of: smul, smulw, smla, smlaw, smlal
*/
#define __ARM_HAVE_HALFWORD_MULTIPLY 1
/* define __ARM_HAVE_LDREXD for ARMv7 architecture
* (also present in ARMv6K, but not implemented in ARMv7-M, neither of which
* we care about)
*/
#if __ARM_ARCH__ >= 7
# define __ARM_HAVE_LDREXD
#endif
/* define _ARM_HAVE_VFP if we have VFPv3
*/
#if __ARM_ARCH__ >= 7 && defined __VFP_FP__
# define __ARM_HAVE_VFP
#endif
/* define _ARM_HAVE_NEON for ARMv7 architecture if we support the
* Neon SIMD instruction set extensions. This also implies
* that VFPv3-D32 is supported.
*/
#if __ARM_ARCH__ >= 7 && defined __ARM_NEON__
# define __ARM_HAVE_NEON
#endif
#endif /* _ARM_MACHINE_CPU_FEATURES_H */

View File

@ -102,8 +102,6 @@
/* 112-127 are reserved for private experiments. */
#define R_ARM_IRELATIVE 160
#define R_ARM_RXPC25 249
#define R_ARM_RSBREL32 250
#define R_ARM_THM_RPC22 251

View File

@ -0,0 +1,79 @@
/* $OpenBSD: endian.h,v 1.3 2005/12/13 00:35:23 millert Exp $ */
/*
* 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.
*/
#ifndef _ARM_ENDIAN_H_
#define _ARM_ENDIAN_H_
#ifdef __GNUC__
/* According to RealView Assembler User's Guide, REV and REV16 are available
* in Thumb code and 16-bit instructions when used in Thumb-2 code.
*
* REV Rd, Rm
* Rd and Rm must both be Lo registers.
*
* REV16 Rd, Rm
* Rd and Rm must both be Lo registers.
*
* The +l constraint takes care of this without constraining us in ARM mode.
*/
#define __swap16md(x) ({ \
register u_int16_t _x = (x); \
__asm__ __volatile__("rev16 %0, %0" : "+l" (_x)); \
_x; \
})
#define __swap32md(x) ({ \
register u_int32_t _x = (x); \
__asm__ __volatile__("rev %0, %0" : "+l" (_x)); \
_x; \
})
#define __swap64md(x) ({ \
u_int64_t _swap64md_x = (x); \
(u_int64_t) __swap32md(_swap64md_x >> 32) | \
(u_int64_t) __swap32md(_swap64md_x & 0xffffffff) << 32; \
})
/* Tell sys/endian.h we have MD variants of the swap macros. */
#define MD_SWAP
#endif /* __GNUC__ */
#if defined(__ARMEB__)
#define _BYTE_ORDER _BIG_ENDIAN
#else
#define _BYTE_ORDER _LITTLE_ENDIAN
#endif
#define __STRICT_ALIGNMENT
#include <sys/types.h>
#include <sys/endian.h>
#endif /* !_ARM_ENDIAN_H_ */

View File

@ -0,0 +1,50 @@
/* $OpenBSD: exec.h,v 1.9 2003/04/17 03:42:14 drahn Exp $ */
/* $NetBSD: exec.h,v 1.6 1994/10/27 04:16:05 cgd Exp $ */
/*
* Copyright (c) 1993 Christopher G. Demetriou
* All rights reserved.
*
* 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 _ARM_EXEC_H_
#define _ARM_EXEC_H_
#define __LDPGSZ 4096
#define NATIVE_EXEC_ELF
#define ARCH_ELFSIZE 32
#define ELF_TARG_CLASS ELFCLASS32
#define ELF_TARG_DATA ELFDATA2LSB
#define ELF_TARG_MACH EM_ARM
#define _NLIST_DO_AOUT
#define _NLIST_DO_ELF
#define _KERN_DO_AOUT
#define _KERN_DO_ELF
#endif /* _ARM_EXEC_H_ */

View File

@ -26,6 +26,10 @@
* SUCH DAMAGE.
*/
/*
* machine/setjmp.h: machine dependent setjmp-related information.
*/
/* _JBLEN is the size of a jmp_buf in longs.
* Do not modify this value or you will break the ABI !
*
@ -33,3 +37,46 @@
* that was replaced by this one.
*/
#define _JBLEN 64
/* According to the ARM AAPCS document, we only need to save
* the following registers:
*
* Core r4-r14
*
* VFP d8-d15 (see section 5.1.2.1)
*
* Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine
* calls; registers s0-s15 (d0-d7, q0-q3) do not need to be preserved
* (and can be used for passing arguments or returning results in standard
* procedure-call variants). Registers d16-d31 (q8-q15), if present, do
* not need to be preserved.
*
* FPSCR saved because GLibc does saves it too.
*
*/
/* The internal structure of a jmp_buf is totally private.
* Current layout (may change in the future):
*
* word name description
* 0 magic magic number
* 1 sigmask signal mask (not used with _setjmp / _longjmp)
* 2 float_base base of float registers (d8 to d15)
* 18 float_state floating-point status and control register
* 19 core_base base of core registers (r4 to r14)
* 30 reserved reserved entries (room to grow)
* 64
*
* NOTE: float_base must be at an even word index, since the
* FP registers will be loaded/stored with instructions
* that expect 8-byte alignment.
*/
#define _JB_MAGIC 0
#define _JB_SIGMASK (_JB_MAGIC+1)
#define _JB_FLOAT_BASE (_JB_SIGMASK+1)
#define _JB_FLOAT_STATE (_JB_FLOAT_BASE + (15-8+1)*2)
#define _JB_CORE_BASE (_JB_FLOAT_STATE+1)
#define _JB_MAGIC__SETJMP 0x4278f500
#define _JB_MAGIC_SETJMP 0x4278f501

View File

@ -40,7 +40,7 @@
ENTRY(__strcat_chk)
pld [r0, #0]
push {r0, lr}
.cfi_adjust_cfa_offset 8
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
push {r4, r5}
@ -177,7 +177,7 @@ ENTRY(__strcat_chk)
.L_strlen_done:
add r2, r3, r4
cmp r2, lr
bhi .L_strcat_chk_failed
bhi __strcat_chk_failed
// Set up the registers for the memcpy code.
mov r1, r5
@ -185,17 +185,20 @@ ENTRY(__strcat_chk)
mov r2, r4
add r0, r0, r3
pop {r4, r5}
.cfi_adjust_cfa_offset -8
.cfi_restore r4
.cfi_restore r5
END(__strcat_chk)
#define MEMCPY_BASE __strcat_chk_memcpy_base
#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
#include "memcpy_base.S"
// Undo the above cfi directives.
ENTRY_PRIVATE(__strcat_chk_failed)
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
.L_strcat_chk_failed:
ldr r0, error_message
ldr r1, error_code
1:
@ -205,7 +208,7 @@ error_code:
.word BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+4)
END(__strcat_chk)
END(__strcat_chk_failed)
.data
error_string:

View File

@ -39,7 +39,7 @@
ENTRY(__strcpy_chk)
pld [r0, #0]
push {r0, lr}
.cfi_adjust_cfa_offset 8
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
@ -149,14 +149,21 @@ ENTRY(__strcpy_chk)
pld [r1, #64]
ldr r0, [sp]
cmp r3, lr
bhs .L_strcpy_chk_failed
bhs __strcpy_chk_failed
// Add 1 for copy length to get the string terminator.
add r2, r3, #1
END(__strcpy_chk)
#define MEMCPY_BASE __strcpy_chk_memcpy_base
#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
#include "memcpy_base.S"
.L_strcpy_chk_failed:
ENTRY_PRIVATE(__strcpy_chk_failed)
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
ldr r0, error_message
ldr r1, error_code
1:
@ -166,7 +173,7 @@ error_code:
.word BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+4)
END(__strcpy_chk)
END(__strcpy_chk_failed)
.data
error_string:

View File

@ -45,7 +45,7 @@
ENTRY(__memcpy_chk)
cmp r2, r3
bhi .L_memcpy_chk_fail
bhi __memcpy_chk_fail
// Fall through to memcpy...
END(__memcpy_chk)
@ -53,20 +53,19 @@ END(__memcpy_chk)
ENTRY(memcpy)
pld [r1, #64]
stmfd sp!, {r0, lr}
.cfi_adjust_cfa_offset 8
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
END(memcpy)
#define MEMCPY_BASE __memcpy_base
#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
#include "memcpy_base.S"
// Undo the cfi directives from above.
.cfi_adjust_cfa_offset -8
.cfi_restore r0
.cfi_restore lr
.L_memcpy_chk_fail:
ENTRY_PRIVATE(__memcpy_chk_fail)
// Preserve lr for backtrace.
push {lr}
.cfi_adjust_cfa_offset 4
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
ldr r0, error_message
@ -78,7 +77,7 @@ error_code:
.word BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+4)
END(memcpy)
END(__memcpy_chk_fail)
.data
error_string:

View File

@ -1,191 +1,123 @@
/***************************************************************************
Copyright (c) 2009-2013 The Linux Foundation. All rights reserved.
/*
* Copyright (C) 2013 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.
*/
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 The Linux Foundation 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 HOLDER 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.
***************************************************************************/
/*
* This code assumes it is running on a processor that supports all arm v7
* instructions, that supports neon instructions, and that has a 32 byte
* cache line.
*/
/* Assumes neon instructions and a cache line size of 64 bytes. */
// Assumes neon instructions and a cache line size of 32 bytes.
#include <machine/cpu-features.h>
#include <machine/asm.h>
ENTRY_PRIVATE(MEMCPY_BASE)
.cfi_def_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
#define PLDOFFS (10)
#define PLDTHRESH (PLDOFFS)
#define BBTHRESH (4096/64)
#define PLDSIZE (64)
/* do we have at least 16-bytes to copy (needed for alignment below) */
cmp r2, #16
blo 5f
#if (PLDOFFS < 1)
#error Routine does not support offsets less than 1
#endif
/* align destination to cache-line for the write-buffer */
rsb r3, r0, #0
ands r3, r3, #0xF
beq 2f
#if (PLDTHRESH < PLDOFFS)
#error PLD threshold must be greater than or equal to the PLD offset
#endif
/* copy up to 15-bytes (count in r3) */
sub r2, r2, r3
movs ip, r3, lsl #31
itt mi
ldrbmi lr, [r1], #1
strbmi lr, [r0], #1
itttt cs
ldrbcs ip, [r1], #1
ldrbcs lr, [r1], #1
strbcs ip, [r0], #1
strbcs lr, [r0], #1
movs ip, r3, lsl #29
bge 1f
// copies 4 bytes, destination 32-bits aligned
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
1: bcc 2f
// copies 8 bytes, destination 64-bits aligned
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0, :64]!
.text
.fpu neon
2: /* make sure we have at least 64 bytes to copy */
subs r2, r2, #64
blo 2f
.L_memcpy_base:
cmp r2, #4
blt .L_neon_lt4
cmp r2, #16
blt .L_neon_lt16
cmp r2, #32
blt .L_neon_16
cmp r2, #64
blt .L_neon_copy_32_a
1: /* The main loop copies 64 bytes at a time */
vld1.8 {d0 - d3}, [r1]!
vld1.8 {d4 - d7}, [r1]!
pld [r1, #(32*8)]
subs r2, r2, #64
vst1.8 {d0 - d3}, [r0, :128]!
vst1.8 {d4 - d7}, [r0, :128]!
bhs 1b
mov r12, r2, lsr #6
cmp r12, #PLDTHRESH
ble .L_neon_copy_64_loop_nopld
2: /* fix-up the remaining count and make sure we have >= 32 bytes left */
adds r2, r2, #32
blo 4f
push {r9, r10}
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r9, 0
.cfi_rel_offset r10, 4
/* Copy 32 bytes. These cache lines were already preloaded */
vld1.8 {d0 - d3}, [r1]!
sub r2, r2, #32
vst1.8 {d0 - d3}, [r0, :128]!
cmp r12, #BBTHRESH
ble .L_neon_prime_pump
4: /* less than 32 left */
add r2, r2, #32
tst r2, #0x10
beq 5f
// copies 16 bytes, 128-bits aligned
vld1.8 {d0, d1}, [r1]!
vst1.8 {d0, d1}, [r0, :128]!
add lr, r0, #0x400
add r9, r1, #(PLDOFFS*PLDSIZE)
sub lr, lr, r9
lsl lr, lr, #21
lsr lr, lr, #21
add lr, lr, #(PLDOFFS*PLDSIZE)
cmp r12, lr, lsr #6
ble .L_neon_prime_pump
5: /* copy up to 15-bytes (count in r2) */
movs ip, r2, lsl #29
bcc 1f
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0]!
1: bge 2f
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
2: movs ip, r2, lsl #31
itt mi
ldrbmi r3, [r1], #1
strbmi r3, [r0], #1
itttt cs
ldrbcs ip, [r1], #1
ldrbcs lr, [r1], #1
strbcs ip, [r0], #1
strbcs lr, [r0], #1
itt gt
movgt r9, #(PLDOFFS)
rsbsgt r9, r9, lr, lsr #6
ble .L_neon_prime_pump
add r10, r1, lr
bic r10, #0x3F
sub r12, r12, lr, lsr #6
cmp r9, r12
itee le
suble r12, r12, r9
movgt r9, r12
movgt r12, #0
pld [r1, #((PLDOFFS-1)*PLDSIZE)]
.L_neon_copy_64_loop_outer_doublepld:
pld [r1, #((PLDOFFS)*PLDSIZE)]
vld1.32 {q0, q1}, [r1]!
vld1.32 {q2, q3}, [r1]!
ldr r3, [r10]
subs r9, r9, #1
vst1.32 {q0, q1}, [r0]!
vst1.32 {q2, q3}, [r0]!
add r10, #64
bne .L_neon_copy_64_loop_outer_doublepld
cmp r12, #0
beq .L_neon_pop_before_nopld
cmp r12, #(512*1024/64)
blt .L_neon_copy_64_loop_outer
.L_neon_copy_64_loop_ddr:
vld1.32 {q0, q1}, [r1]!
vld1.32 {q2, q3}, [r1]!
pld [r10]
subs r12, r12, #1
vst1.32 {q0, q1}, [r0]!
vst1.32 {q2, q3}, [r0]!
add r10, #64
bne .L_neon_copy_64_loop_ddr
b .L_neon_pop_before_nopld
.L_neon_prime_pump:
mov lr, #(PLDOFFS*PLDSIZE)
add r10, r1, #(PLDOFFS*PLDSIZE)
bic r10, #0x3F
sub r12, r12, #PLDOFFS
ldr r3, [r10, #(-1*PLDSIZE)]
.L_neon_copy_64_loop_outer:
vld1.32 {q0, q1}, [r1]!
vld1.32 {q2, q3}, [r1]!
ldr r3, [r10]
subs r12, r12, #1
vst1.32 {q0, q1}, [r0]!
vst1.32 {q2, q3}, [r0]!
add r10, #64
bne .L_neon_copy_64_loop_outer
.L_neon_pop_before_nopld:
mov r12, lr, lsr #6
pop {r9, r10}
.cfi_adjust_cfa_offset -8
.cfi_restore r9
.cfi_restore r10
.L_neon_copy_64_loop_nopld:
vld1.32 {q8, q9}, [r1]!
vld1.32 {q10, q11}, [r1]!
subs r12, r12, #1
vst1.32 {q8, q9}, [r0]!
vst1.32 {q10, q11}, [r0]!
bne .L_neon_copy_64_loop_nopld
ands r2, r2, #0x3f
beq .L_neon_exit
.L_neon_copy_32_a:
movs r3, r2, lsl #27
bcc .L_neon_16
vld1.32 {q0,q1}, [r1]!
vst1.32 {q0,q1}, [r0]!
.L_neon_16:
bpl .L_neon_lt16
vld1.32 {q8}, [r1]!
vst1.32 {q8}, [r0]!
ands r2, r2, #0x0f
beq .L_neon_exit
.L_neon_lt16:
movs r3, r2, lsl #29
bcc 1f
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0]!
1:
bge .L_neon_lt4
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
.L_neon_lt4:
movs r2, r2, lsl #31
itt cs
ldrhcs r3, [r1], #2
strhcs r3, [r0], #2
itt mi
ldrbmi r3, [r1]
strbmi r3, [r0]
.L_neon_exit:
pop {r0, pc}
ldmfd sp!, {r0, lr}
bx lr
END(MEMCPY_BASE)

View File

@ -37,7 +37,6 @@
*/
.fpu neon
.syntax unified
ENTRY(__memset_chk)
cmp r2, r3
@ -69,7 +68,10 @@ END(bzero)
/* memset() returns its first argument. */
ENTRY(memset)
mov r3, r0
stmfd sp!, {r0}
.cfi_def_cfa_offset 4
.cfi_rel_offset r0, 0
vdup.8 q0, r1
/* make sure we have at least 32 bytes to write */
@ -79,7 +81,7 @@ ENTRY(memset)
1: /* The main loop writes 32 bytes at a time */
subs r2, r2, #32
vst1.8 {d0 - d3}, [r3]!
vst1.8 {d0 - d3}, [r0]!
bhs 1b
2: /* less than 32 left */
@ -88,17 +90,18 @@ ENTRY(memset)
beq 3f
// writes 16 bytes, 128-bits aligned
vst1.8 {d0, d1}, [r3]!
vst1.8 {d0, d1}, [r0]!
3: /* write up to 15-bytes (count in r2) */
movs ip, r2, lsl #29
bcc 1f
vst1.8 {d0}, [r3]!
vst1.8 {d0}, [r0]!
1: bge 2f
vst1.32 {d0[0]}, [r3]!
vst1.32 {d0[0]}, [r0]!
2: movs ip, r2, lsl #31
strbmi r1, [r3], #1
strbcs r1, [r3], #1
strbcs r1, [r3], #1
strmib r1, [r0], #1
strcsb r1, [r0], #1
strcsb r1, [r0], #1
ldmfd sp!, {r0}
bx lr
END(memset)

View File

@ -1,18 +1,3 @@
libc_openbsd_src_files_exclude_arm += \
upstream-openbsd/lib/libc/string/memmove.c \
upstream-openbsd/lib/libc/string/stpcpy.c \
upstream-openbsd/lib/libc/string/stpcpy.c \
upstream-openbsd/lib/libc/string/strcat.c \
libc_bionic_src_files_exclude_arm += \
arch-arm/generic/bionic/memcpy.S \
arch-arm/generic/bionic/memset.S \
arch-arm/generic/bionic/strcmp.S \
arch-arm/generic/bionic/strcpy.S \
arch-arm/generic/bionic/strlen.c \
bionic/__strcat_chk.cpp \
bionic/__strcpy_chk.cpp \
libc_bionic_src_files_arm += \
arch-arm/krait/bionic/memcpy.S \
arch-arm/krait/bionic/memset.S \
@ -26,6 +11,4 @@ libc_bionic_src_files_arm += \
arch-arm/cortex-a15/bionic/strcat.S \
arch-arm/cortex-a15/bionic/strcpy.S \
arch-arm/cortex-a15/bionic/strlen.S \
libc_bionic_src_files_arm += \
arch-arm/denver/bionic/memmove.S \
bionic/memmove.c \

View File

@ -1,23 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(___mremap)
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_mremap
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(___mremap)
.hidden ___mremap

View File

@ -1,15 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(___rt_sigqueueinfo)
mov ip, r7
ldr r7, =__NR_rt_sigqueueinfo
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno_internal
END(___rt_sigqueueinfo)
.hidden ___rt_sigqueueinfo

View File

@ -1,22 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(__preadv64)
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_preadv
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(__preadv64)

View File

@ -1,22 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(__pwritev64)
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_pwritev
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(__pwritev64)

View File

@ -13,4 +13,5 @@ ENTRY(_exit)
b __set_errno_internal
END(_exit)
ALIAS_SYMBOL(_Exit, _exit)
.globl _Exit
.equ _Exit, _exit

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(___close)
ENTRY(close)
mov ip, r7
ldr r7, =__NR_close
swi #0
@ -11,5 +11,4 @@ ENTRY(___close)
bxls lr
neg r0, r0
b __set_errno_internal
END(___close)
.hidden ___close
END(close)

View File

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

View File

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

View File

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

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(___flistxattr)
ENTRY(flistxattr)
mov ip, r7
ldr r7, =__NR_flistxattr
swi #0
@ -11,5 +11,4 @@ ENTRY(___flistxattr)
bxls lr
neg r0, r0
b __set_errno_internal
END(___flistxattr)
.hidden ___flistxattr
END(flistxattr)

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

@ -13,4 +13,5 @@ ENTRY(fstat64)
b __set_errno_internal
END(fstat64)
ALIAS_SYMBOL(fstat, fstat64)
.globl fstat
.equ fstat, fstat64

View File

@ -13,4 +13,5 @@ ENTRY(fstatat64)
b __set_errno_internal
END(fstatat64)
ALIAS_SYMBOL(fstatat, fstatat64)
.globl fstatat
.equ fstatat, fstatat64

View File

@ -2,13 +2,13 @@
#include <private/bionic_asm.h>
ENTRY(sethostname)
ENTRY(ftruncate)
mov ip, r7
ldr r7, =__NR_sethostname
ldr r7, =__NR_ftruncate
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno_internal
END(sethostname)
END(ftruncate)

View File

@ -0,0 +1,14 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(mremap)
mov ip, r7
ldr r7, =__NR_mremap
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno_internal
END(mremap)

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)

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