Remove components that were moved to sdk.git and update build scripts.

This commit is contained in:
Xavier Ducrohet
2009-11-17 15:11:59 -08:00
parent f4c63fae0c
commit 19cb54ea7d
1204 changed files with 46 additions and 193799 deletions

View File

@@ -18,10 +18,10 @@
# These are the files that comprise that SDK
#
# version files for the SDK updater
development/tools/scripts/doc_source.properties docs/source.properties
development/tools/scripts/tools_source.properties tools/source.properties
development/tools/scripts/platform_source.properties platforms/${PLATFORM_NAME}/source.properties
# version files for the SDK updater, from sdk.git
sdk/scripts/doc_source.properties docs/source.properties
sdk/scripts/tools_source.properties tools/source.properties
sdk/scripts/platform_source.properties platforms/${PLATFORM_NAME}/source.properties
# host tools from out/host/$(HOST_OS)-$(HOST_ARCH)/
bin/aapt platforms/${PLATFORM_NAME}/tools/aapt
@@ -42,29 +42,32 @@ framework/org.eclipse.equinox.common_3.4.0.v20080421-2006.jar tools/lib/org.ecli
framework/org.eclipse.jface_3.4.2.M20090107-0800.jar tools/lib/org.eclipse.jface_3.4.2.M20090107-0800.jar
framework/osgi.jar tools/lib/osgi.jar
# copy build prop from out/.../sdk/
sdk/sdk-build.prop platforms/${PLATFORM_NAME}/build.prop
development/tools/scripts/plugin.prop tools/lib/plugin.prop
# copy plugin.prop from sdk.git
sdk/scripts/plugin.prop tools/lib/plugin.prop
# the aidl precompiled include
obj/framework.aidl platforms/${PLATFORM_NAME}/framework.aidl
# sdk scripts
development/tools/scripts/AndroidManifest.template platforms/${PLATFORM_NAME}/templates/AndroidManifest.template
development/tools/scripts/AndroidManifest.tests.template platforms/${PLATFORM_NAME}/templates/AndroidManifest.tests.template
development/tools/scripts/java_file.template platforms/${PLATFORM_NAME}/templates/java_file.template
development/tools/scripts/java_tests_file.template platforms/${PLATFORM_NAME}/templates/java_tests_file.template
development/tools/scripts/layout.template platforms/${PLATFORM_NAME}/templates/layout.template
development/tools/scripts/strings.template platforms/${PLATFORM_NAME}/templates/strings.template
development/tools/scripts/android_rules.xml platforms/${PLATFORM_NAME}/templates/android_rules.xml
development/tools/scripts/android_test_rules.xml platforms/${PLATFORM_NAME}/templates/android_test_rules.xml
development/tools/scripts/icon_ldpi.png platforms/${PLATFORM_NAME}/templates/icon_ldpi.png
development/tools/scripts/icon_mdpi.png platforms/${PLATFORM_NAME}/templates/icon_mdpi.png
development/tools/scripts/icon_hdpi.png platforms/${PLATFORM_NAME}/templates/icon_hdpi.png
development/tools/scripts/build.template tools/lib/build.template
development/tools/scripts/devices.xml tools/lib/devices.xml
# sdk.git scripts
sdk/scripts/AndroidManifest.template platforms/${PLATFORM_NAME}/templates/AndroidManifest.template
sdk/scripts/AndroidManifest.tests.template platforms/${PLATFORM_NAME}/templates/AndroidManifest.tests.template
sdk/scripts/java_file.template platforms/${PLATFORM_NAME}/templates/java_file.template
sdk/scripts/java_tests_file.template platforms/${PLATFORM_NAME}/templates/java_tests_file.template
sdk/scripts/layout.template platforms/${PLATFORM_NAME}/templates/layout.template
sdk/scripts/strings.template platforms/${PLATFORM_NAME}/templates/strings.template
sdk/scripts/android_rules.xml platforms/${PLATFORM_NAME}/templates/android_rules.xml
sdk/scripts/android_test_rules.xml platforms/${PLATFORM_NAME}/templates/android_test_rules.xml
sdk/scripts/icon_ldpi.png platforms/${PLATFORM_NAME}/templates/icon_ldpi.png
sdk/scripts/icon_mdpi.png platforms/${PLATFORM_NAME}/templates/icon_mdpi.png
sdk/scripts/icon_hdpi.png platforms/${PLATFORM_NAME}/templates/icon_hdpi.png
sdk/scripts/build.template tools/lib/build.template
sdk/scripts/devices.xml tools/lib/devices.xml
# emacs support
development/tools/scripts/android.el tools/lib/android.el
# emacs support from sdk.git
sdk/scripts/android.el tools/lib/android.el
# samples
development/apps/GestureBuilder platforms/${PLATFORM_NAME}/samples/GestureBuilder
@@ -156,20 +159,20 @@ userdata.img platforms/${PLATFORM_NAME}/images/userdata.img
prebuilt/android-arm/kernel/kernel-qemu platforms/${PLATFORM_NAME}/images/kernel-qemu
external/qemu/android/avd/hardware-properties.ini tools/lib/hardware-properties.ini
# emulator skins
development/emulator/skins/QVGA platforms/${PLATFORM_NAME}/skins/QVGA
development/emulator/skins/WQVGA432 platforms/${PLATFORM_NAME}/skins/WQVGA432
development/emulator/skins/WQVGA400 platforms/${PLATFORM_NAME}/skins/WQVGA400
development/emulator/skins/HVGA platforms/${PLATFORM_NAME}/skins/HVGA
development/emulator/skins/WVGA800 platforms/${PLATFORM_NAME}/skins/WVGA800
development/emulator/skins/WVGA854 platforms/${PLATFORM_NAME}/skins/WVGA854
# emulator skins from sdk.git
sdk/emulator/skins/QVGA platforms/${PLATFORM_NAME}/skins/QVGA
sdk/emulator/skins/WQVGA432 platforms/${PLATFORM_NAME}/skins/WQVGA432
sdk/emulator/skins/WQVGA400 platforms/${PLATFORM_NAME}/skins/WQVGA400
sdk/emulator/skins/HVGA platforms/${PLATFORM_NAME}/skins/HVGA
sdk/emulator/skins/WVGA800 platforms/${PLATFORM_NAME}/skins/WVGA800
sdk/emulator/skins/WVGA854 platforms/${PLATFORM_NAME}/skins/WVGA854
# NOTICE files are copied by build/core/Makefile
development/tools/scripts/sdk_files_NOTICE.txt platforms/${PLATFORM_NAME}/templates/NOTICE.txt
development/tools/scripts/sdk_files_NOTICE.txt platforms/${PLATFORM_NAME}/samples/NOTICE.txt
development/tools/scripts/sdk_files_NOTICE.txt platforms/${PLATFORM_NAME}/data/NOTICE.txt
development/tools/scripts/sdk_files_NOTICE.txt platforms/${PLATFORM_NAME}/skins/NOTICE.txt
development/tools/scripts/sdk_files_NOTICE.txt platforms/${PLATFORM_NAME}/tools/NOTICE.txt
# NOTICE files are copied by build/core/Makefile from sdk.git
sdk/scripts/sdk_files_NOTICE.txt platforms/${PLATFORM_NAME}/templates/NOTICE.txt
sdk/scripts/sdk_files_NOTICE.txt platforms/${PLATFORM_NAME}/samples/NOTICE.txt
sdk/scripts/sdk_files_NOTICE.txt platforms/${PLATFORM_NAME}/data/NOTICE.txt
sdk/scripts/sdk_files_NOTICE.txt platforms/${PLATFORM_NAME}/skins/NOTICE.txt
sdk/scripts/sdk_files_NOTICE.txt platforms/${PLATFORM_NAME}/tools/NOTICE.txt
# the readme
development/docs/SDK_RELEASE_NOTES RELEASE_NOTES.html
@@ -197,5 +200,5 @@ frameworks/base/data/fonts/DroidSerif-BoldItalic.ttf platforms/${PLATFORM_NAME}/
frameworks/base/data/fonts/DroidSerif-Italic.ttf platforms/${PLATFORM_NAME}/data/fonts/DroidSerif-Italic.ttf
frameworks/base/data/fonts/DroidSerif-Regular.ttf platforms/${PLATFORM_NAME}/data/fonts/DroidSerif-Regular.ttf
# empty add-on folder with just a readme
development/tools/scripts/README_add-ons.txt add-ons/README.txt
# empty add-on folder with just a readme copied from sdk.git
sdk/scripts/README_add-ons.txt add-ons/README.txt

View File

@@ -163,13 +163,13 @@ function package() {
cp -v /cygdrive/c/cygwin/bin/mgwz.dll "$TOOLS"/
# Update a bunch of bat files
cp -v development/tools/apkbuilder/etc/apkbuilder.bat "$TOOLS"/
cp -v development/tools/ddms/app/etc/ddms.bat "$TOOLS"/
cp -v development/tools/traceview/etc/traceview.bat "$TOOLS"/
cp -v development/tools/hierarchyviewer/etc/hierarchyviewer.bat "$TOOLS"/
cp -v development/tools/layoutopt/app/etc/layoutopt.bat "$TOOLS"/
cp -v development/tools/draw9patch/etc/draw9patch.bat "$TOOLS"/
cp -v development/tools/sdkmanager/app/etc/android.bat "$TOOLS"/
cp -v sdk/apkbuilder/etc/apkbuilder.bat "$TOOLS"/
cp -v sdk/ddms/app/etc/ddms.bat "$TOOLS"/
cp -v sdk/traceview/etc/traceview.bat "$TOOLS"/
cp -v sdk/hierarchyviewer/etc/hierarchyviewer.bat "$TOOLS"/
cp -v sdk/layoutopt/app/etc/layoutopt.bat "$TOOLS"/
cp -v sdk/draw9patch/etc/draw9patch.bat "$TOOLS"/
cp -v sdk/sdkmanager/app/etc/android.bat "$TOOLS"/
# Put the JetCreator tools, content and docs (not available in the linux SDK)
JET="$TOOLS/Jet"

View File

@@ -1,7 +0,0 @@
key 200 MEDIA_PLAY_PAUSE WAKE
key 201 MEDIA_PLAY_PAUSE WAKE
key 166 MEDIA_STOP WAKE
key 163 MEDIA_NEXT WAKE
key 165 MEDIA_PREVIOUS WAKE
key 168 MEDIA_REWIND WAKE
key 208 MEDIA_FAST_FORWARD WAKE

View File

@@ -1,18 +0,0 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := qwerty.kcm
include $(BUILD_KEY_CHAR_MAP)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := qwerty2.kcm
include $(BUILD_KEY_CHAR_MAP)
file := $(TARGET_OUT_KEYLAYOUT)/qwerty.kl
ALL_PREBUILT += $(file)
$(file): $(LOCAL_PATH)/qwerty.kl | $(ACP)
$(transform-prebuilt-to-target)
file := $(TARGET_OUT_KEYLAYOUT)/AVRCP.kl
ALL_PREBUILT += $(file)
$(file) : $(LOCAL_PATH)/AVRCP.kl | $(ACP)
$(transform-prebuilt-to-target)

View File

@@ -1,64 +0,0 @@
[type=QWERTY]
# keycode display number base caps fn caps_fn
A 'A' '2' 'a' 'A' '#' 0x00
B 'B' '2' 'b' 'B' '<' 0x00
C 'C' '2' 'c' 'C' '9' 0x00E7
D 'D' '3' 'd' 'D' '5' 0x00
E 'E' '3' 'e' 'E' '2' 0x0301
F 'F' '3' 'f' 'F' '6' 0x00A5
G 'G' '4' 'g' 'G' '-' '_'
H 'H' '4' 'h' 'H' '[' '{'
I 'I' '4' 'i' 'I' '$' 0x0302
J 'J' '5' 'j' 'J' ']' '}'
K 'K' '5' 'k' 'K' '"' '~'
L 'L' '5' 'l' 'L' ''' '`'
M 'M' '6' 'm' 'M' '!' 0x00
N 'N' '6' 'n' 'N' '>' 0x0303
O 'O' '6' 'o' 'O' '(' 0x00
P 'P' '7' 'p' 'P' ')' 0x00
Q 'Q' '7' 'q' 'Q' '*' 0x0300
R 'R' '7' 'r' 'R' '3' 0x20AC
S 'S' '7' 's' 'S' '4' 0x00DF
T 'T' '8' 't' 'T' '+' 0x00A3
U 'U' '8' 'u' 'U' '&' 0x0308
V 'V' '8' 'v' 'V' '=' '^'
W 'W' '9' 'w' 'W' '1' 0x00
X 'X' '9' 'x' 'X' '8' 0xEF00
Y 'Y' '9' 'y' 'Y' '%' 0x00A1
Z 'Z' '9' 'z' 'Z' '7' 0x00
# on pc keyboards
COMMA ',' ',' ',' ';' ';' '|'
PERIOD '.' '.' '.' ':' ':' 0x2026
AT '@' '0' '@' '0' '0' 0x2022
SLASH '/' '/' '/' '?' '?' '\'
SPACE 0x20 0x20 0x20 0x20 0xEF01 0xEF01
ENTER 0xa 0xa 0xa 0xa 0xa 0xa
TAB 0x9 0x9 0x9 0x9 0x9 0x9
0 '0' '0' '0' ')' ')' ')'
1 '1' '1' '1' '!' '!' '!'
2 '2' '2' '2' '@' '@' '@'
3 '3' '3' '3' '#' '#' '#'
4 '4' '4' '4' '$' '$' '$'
5 '5' '5' '5' '%' '%' '%'
6 '6' '6' '6' '^' '^' '^'
7 '7' '7' '7' '&' '&' '&'
8 '8' '8' '8' '*' '*' '*'
9 '9' '9' '9' '(' '(' '('
GRAVE '`' '`' '`' '~' '`' '~'
MINUS '-' '-' '-' '_' '-' '_'
EQUALS '=' '=' '=' '+' '=' '+'
LEFT_BRACKET '[' '[' '[' '{' '[' '{'
RIGHT_BRACKET ']' ']' ']' '}' ']' '}'
BACKSLASH '\' '\' '\' '|' '\' '|'
SEMICOLON ';' ';' ';' ':' ';' ':'
APOSTROPHE ''' ''' ''' '"' ''' '"'
STAR '*' '*' '*' '*' '*' '*'
POUND '#' '#' '#' '#' '#' '#'
PLUS '+' '+' '+' '+' '+' '+'

View File

@@ -1,89 +0,0 @@
key 399 GRAVE
key 2 1
key 3 2
key 4 3
key 5 4
key 6 5
key 7 6
key 8 7
key 9 8
key 10 9
key 11 0
key 158 BACK WAKE_DROPPED
key 230 SOFT_RIGHT WAKE
key 60 SOFT_RIGHT WAKE
key 107 ENDCALL WAKE_DROPPED
key 62 ENDCALL WAKE_DROPPED
key 229 MENU WAKE_DROPPED
key 139 MENU WAKE_DROPPED
key 59 MENU WAKE_DROPPED
key 127 SEARCH WAKE_DROPPED
key 217 SEARCH WAKE_DROPPED
key 228 POUND
key 227 STAR
key 231 CALL WAKE_DROPPED
key 61 CALL WAKE_DROPPED
key 232 DPAD_CENTER WAKE_DROPPED
key 108 DPAD_DOWN WAKE_DROPPED
key 103 DPAD_UP WAKE_DROPPED
key 102 HOME WAKE
key 105 DPAD_LEFT WAKE_DROPPED
key 106 DPAD_RIGHT WAKE_DROPPED
key 115 VOLUME_UP
key 114 VOLUME_DOWN
key 116 POWER WAKE
key 212 CAMERA
key 16 Q
key 17 W
key 18 E
key 19 R
key 20 T
key 21 Y
key 22 U
key 23 I
key 24 O
key 25 P
key 26 LEFT_BRACKET
key 27 RIGHT_BRACKET
key 43 BACKSLASH
key 30 A
key 31 S
key 32 D
key 33 F
key 34 G
key 35 H
key 36 J
key 37 K
key 38 L
key 39 SEMICOLON
key 40 APOSTROPHE
key 14 DEL
key 44 Z
key 45 X
key 46 C
key 47 V
key 48 B
key 49 N
key 50 M
key 51 COMMA
key 52 PERIOD
key 53 SLASH
key 28 ENTER
key 56 ALT_LEFT
key 100 ALT_RIGHT
key 42 SHIFT_LEFT
key 54 SHIFT_RIGHT
key 15 TAB
key 57 SPACE
key 150 EXPLORER
key 155 ENVELOPE
key 12 MINUS
key 13 EQUALS
key 215 AT

View File

@@ -1,81 +0,0 @@
[type=QWERTY]
# this keymap is to be used in the emulator only. note
# that I have liberally modified certain key strokes to
# make it more usable in this context. the main differences
# with the reference keyboard image are:
#
# - cap-2 produces '@', and not '"', without that, typing
# email addresses becomes a major pain with a qwerty
# keyboard. note that you can type '"' with fn-E anyway.
#
# - cap-COMMA and cap-PERIOD return '<' and '>', instead
# of nothing.
#
#
# keycode display number base caps fn caps_fn
A 'A' '2' 'a' 'A' 'a' 'A'
B 'B' '2' 'b' 'B' 'b' 'B'
C 'C' '2' 'c' 'C' 0x00e7 0x00E7
D 'D' '3' 'd' 'D' ''' '''
E 'E' '3' 'e' 'E' '"' 0x0301
F 'F' '3' 'f' 'F' '[' '['
G 'G' '4' 'g' 'G' ']' ']'
H 'H' '4' 'h' 'H' '<' '<'
I 'I' '4' 'i' 'I' '-' 0x0302
J 'J' '5' 'j' 'J' '>' '>'
K 'K' '5' 'k' 'K' ';' '~'
L 'L' '5' 'l' 'L' ':' '`'
M 'M' '6' 'm' 'M' '%' 0x00
N 'N' '6' 'n' 'N' 0x00 0x0303
O 'O' '6' 'o' 'O' '+' '+'
P 'P' '7' 'p' 'P' '=' 0x00A5
Q 'Q' '7' 'q' 'Q' '|' 0x0300
R 'R' '7' 'r' 'R' '`' 0x20AC
S 'S' '7' 's' 'S' '\' 0x00DF
T 'T' '8' 't' 'T' '{' 0x00A3
U 'U' '8' 'u' 'U' '_' 0x0308
V 'V' '8' 'v' 'V' 'v' 'V'
W 'W' '9' 'w' 'W' '~' '~'
X 'X' '9' 'x' 'X' 'x' 0xEF00
Y 'Y' '9' 'y' 'Y' '}' 0x00A1
Z 'Z' '9' 'z' 'Z' 'z' 'Z'
COMMA ',' ',' ',' '<' ',' ','
PERIOD '.' '.' '.' '>' '.' 0x2026
AT '@' '@' '@' '@' '@' 0x2022
SLASH '/' '/' '/' '?' '?' '?'
SPACE 0x20 0x20 0x20 0x20 0xEF01 0xEF01
ENTER 0xa 0xa 0xa 0xa 0xa 0xa
0 '0' '0' '0' ')' ')' ')'
1 '1' '1' '1' '!' '!' '!'
2 '2' '2' '2' '@' '@' '@'
3 '3' '3' '3' '#' '#' '#'
4 '4' '4' '4' '$' '$' '$'
5 '5' '5' '5' '%' '%' '%'
6 '6' '6' '6' '^' '^' '^'
7 '7' '7' '7' '&' '&' '&'
8 '8' '8' '8' '*' '*' '*'
9 '9' '9' '9' '(' '(' '('
# the rest is for a qwerty keyboard
#
TAB 0x9 0x9 0x9 0x9 0x9 0x9
GRAVE '`' '`' '`' '~' '`' '~'
MINUS '-' '-' '-' '_' '-' '_'
EQUALS '=' '=' '=' '+' '=' '+'
LEFT_BRACKET '[' '[' '[' '{' '[' '{'
RIGHT_BRACKET ']' ']' ']' '}' ']' '}'
BACKSLASH '\' '\' '\' '|' '\' '|'
SEMICOLON ';' ';' ';' ':' ';' ':'
APOSTROPHE ''' ''' ''' '"' ''' '"'
STAR '*' '*' '*' '*' '*' '*'
POUND '#' '#' '#' '#' '#' '#'
PLUS '+' '+' '+' '+' '+' '+'

View File

@@ -1,11 +0,0 @@
# Copyright 2006 The Android Open Source Project
LOCAL_PATH:= $(call my-dir)
# host executable
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= mksdcard.c
LOCAL_MODULE = mksdcard
include $(BUILD_HOST_EXECUTABLE)

View File

@@ -1,304 +0,0 @@
/* mksdcard.c
**
** Copyright 2007, The Android Open Source Project
**
** 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 Google 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 Google 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 Google 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.
*/
/* a simple and portable program used to generate a blank FAT32 image file
*
* usage: mksdcard [-l label] <size> <filename>
*/
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
/* believe me, you *don't* want to change these constants !! */
#define BYTES_PER_SECTOR 512
#define RESERVED_SECTORS 32
#define BACKUP_BOOT_SECTOR 6
#define NUM_FATS 2
typedef long long Wide; /* might be something else if you don't use GCC */
typedef unsigned char Byte;
typedef Byte* Bytes;
#define BYTE_(p,i) (((Bytes)(p))[(i)])
#define POKEB(p,v) BYTE_(p,0) = (Byte)(v)
#define POKES(p,v) ( BYTE_(p,0) = (Byte)(v), BYTE_(p,1) = (Byte)((v) >> 8) )
#define POKEW(p,v) ( BYTE_(p,0) = (Byte)(v), BYTE_(p,1) = (Byte)((v) >> 8), BYTE_(p,2) = (Byte)((v) >> 16), BYTE_(p,3) = (Byte)((v) >> 24) )
static Byte s_boot_sector [ BYTES_PER_SECTOR ]; /* boot sector */
static Byte s_fsinfo_sector [ BYTES_PER_SECTOR ]; /* FS Info sector */
static Byte s_fat_head [ BYTES_PER_SECTOR ]; /* first FAT sector */
static Byte s_zero_sector [ BYTES_PER_SECTOR ]; /* empty sector */
/* this is the date and time when creating the disk */
static int
get_serial_id( void )
{
unsigned short lo, hi, mid;
time_t now = time(NULL);
struct tm tm = gmtime( &now )[0];
lo = (unsigned short)(tm.tm_mday + ((tm.tm_mon+1) << 8) + (tm.tm_sec << 8));
hi = (unsigned short)(tm.tm_min + (tm.tm_hour << 8) + (tm.tm_year + 1900));
return lo + (hi << 16);
}
static int
get_sectors_per_cluster( Wide disk_size )
{
Wide disk_MB = disk_size/(1024*1024);
if (disk_MB < 260)
return 1;
if (disk_MB < 8192)
return 4;
if (disk_MB < 16384)
return 8;
if (disk_MB < 32768)
return 16;
return 32;
}
static int
get_sectors_per_fat( Wide disk_size, int sectors_per_cluster )
{
Wide divider;
/* weird computation from MS - see fatgen103.doc for details */
disk_size -= RESERVED_SECTORS * BYTES_PER_SECTOR; /* don't count 32 reserved sectors */
disk_size /= BYTES_PER_SECTOR; /* disk size in sectors */
divider = ((256 * sectors_per_cluster) + NUM_FATS) / 2;
return (int)( (disk_size + (divider-1)) / divider );
}
static void
boot_sector_init( Bytes boot, Bytes info, Wide disk_size, const char* label )
{
int sectors_per_cluster = get_sectors_per_cluster(disk_size);
int sectors_per_fat = get_sectors_per_fat(disk_size, sectors_per_cluster);
int sectors_per_disk = (int)(disk_size / BYTES_PER_SECTOR);
int serial_id = get_serial_id();
int free_count;
if (label == NULL)
label = "SDCARD";
POKEB(boot, 0xeb);
POKEB(boot+1, 0x5a);
POKEB(boot+2, 0x90);
strcpy( (char*)boot + 3, "MSWIN4.1" );
POKES( boot + 0x0b, BYTES_PER_SECTOR ); /* sector size */
POKEB( boot + 0xd, sectors_per_cluster ); /* sectors per cluster */
POKES( boot + 0xe, RESERVED_SECTORS ); /* reserved sectors before first FAT */
POKEB( boot + 0x10, NUM_FATS ); /* number of FATs */
POKES( boot + 0x11, 0 ); /* max root directory entries for FAT12/FAT16, 0 for FAT32 */
POKES( boot + 0x13, 0 ); /* total sectors, 0 to use 32-bit value at offset 0x20 */
POKEB( boot + 0x15, 0xF8 ); /* media descriptor, 0xF8 == hard disk */
POKES( boot + 0x16, 0 ); /* Sectors per FAT for FAT12/16, 0 for FAT32 */
POKES( boot + 0x18, 9 ); /* Sectors per track (whatever) */
POKES( boot + 0x1a, 2 ); /* Number of heads (whatever) */
POKEW( boot + 0x1c, 0 ); /* Hidden sectors */
POKEW( boot + 0x20, sectors_per_disk ); /* Total sectors */
/* extension */
POKEW( boot + 0x24, sectors_per_fat ); /* Sectors per FAT */
POKES( boot + 0x28, 0 ); /* FAT flags */
POKES( boot + 0x2a, 0 ); /* version */
POKEW( boot + 0x2c, 2 ); /* cluster number of root directory start */
POKES( boot + 0x30, 1 ); /* sector number of FS information sector */
POKES( boot + 0x32, BACKUP_BOOT_SECTOR ); /* sector number of a copy of this boot sector */
POKEB( boot + 0x40, 0x80 ); /* physical drive number */
POKEB( boot + 0x42, 0x29 ); /* extended boot signature ?? */
POKEW( boot + 0x43, serial_id ); /* serial ID */
strncpy( (char*)boot + 0x47, label, 11 ); /* Volume Label */
memcpy( boot + 0x52, "FAT32 ", 8 ); /* FAT system type, padded with 0x20 */
POKEB( boot + BYTES_PER_SECTOR-2, 0x55 ); /* boot sector signature */
POKEB( boot + BYTES_PER_SECTOR-1, 0xAA );
/* FSInfo sector */
free_count = sectors_per_disk - 32 - 2*sectors_per_fat;
POKEW( info + 0, 0x41615252 );
POKEW( info + 484, 0x61417272 );
POKEW( info + 488, free_count ); /* number of free clusters */
POKEW( info + 492, 3 ); /* next free clusters, 0-1 reserved, 2 is used for the root dir */
POKEW( info + 508, 0xAA550000 );
}
static void
fat_init( Bytes fat )
{
POKEW( fat, 0x0ffffff8 ); /* reserve cluster 1, media id in low byte */
POKEW( fat + 4, 0x0fffffff ); /* reserve cluster 2 */
POKEW( fat + 8, 0x0fffffff ); /* end of clust chain for root dir */
}
static int
write_sector( FILE* file, Bytes sector )
{
return fwrite( sector, 1, 512, file ) != 512;
}
static int
write_empty( FILE* file, Wide count )
{
static Byte empty[64*1024];
count *= 512;
while (count > 0) {
int len = sizeof(empty);
if (len > count)
len = count;
if ( fwrite( empty, 1, len, file ) != (size_t)len )
return 1;
count -= len;
}
return 0;
}
static void usage (void)
{
fprintf(stderr, "mksdcard: create a blank FAT32 image to be used with the Android emulator\n" );
fprintf(stderr, "usage: mksdcard [-l label] <size> <file>\n\n");
fprintf(stderr, " if <size> is a simple integer, it specifies a size in bytes\n" );
fprintf(stderr, " if <size> is an integer followed by 'K', it specifies a size in KiB\n" );
fprintf(stderr, " if <size> is an integer followed by 'M', it specifies a size in MiB\n" );
exit(1);
}
int main( int argc, char** argv )
{
Wide disk_size;
int sectors_per_fat;
int sectors_per_disk;
char* end;
const char* label = NULL;
FILE* f;
for ( ; argc > 1 && argv[1][0] == '-'; argc--, argv++ )
{
char* arg = argv[1] + 1;
switch (arg[0]) {
case 'l':
if (arg[1] != 0)
arg += 2;
else {
argc--;
argv++;
if (argc <= 1)
usage();
arg = argv[1];
}
label = arg;
break;
default:
usage();
}
}
if (argc != 3)
usage();
disk_size = strtol( argv[1], &end, 10 );
if (disk_size == 0 && errno == EINVAL)
usage();
if (*end == 'K')
disk_size *= 1024;
else if (*end == 'M')
disk_size *= 1024*1024;
if (disk_size < 8*1024*1024)
fprintf(stderr, "### WARNING : SD Card images < 8 MB cannot be used with the Android emulator\n");
sectors_per_disk = disk_size / 512;
sectors_per_fat = get_sectors_per_fat( disk_size, get_sectors_per_cluster( disk_size ) );
boot_sector_init( s_boot_sector, s_fsinfo_sector, disk_size, NULL );
fat_init( s_fat_head );
f = fopen( argv[2], "wb" );
if ( !f ) {
fprintf(stderr, "could not create file '%s', aborting...\n", argv[2] );
}
/* here's the layout:
*
* boot_sector
* fsinfo_sector
* empty
* backup boot sector
* backup fsinfo sector
* RESERVED_SECTORS - 4 empty sectors (if backup sectors), or RESERVED_SECTORS - 2 (if no backup)
* first fat
* second fat
* zero sectors
*/
if ( write_sector( f, s_boot_sector ) ) goto FailWrite;
if ( write_sector( f, s_fsinfo_sector ) ) goto FailWrite;
if ( BACKUP_BOOT_SECTOR > 0 ) {
if ( write_empty( f, BACKUP_BOOT_SECTOR - 2 ) ) goto FailWrite;
if ( write_sector( f, s_boot_sector ) ) goto FailWrite;
if ( write_sector( f, s_fsinfo_sector ) ) goto FailWrite;
if ( write_empty( f, RESERVED_SECTORS - 2 - BACKUP_BOOT_SECTOR ) ) goto FailWrite;
}
else
if ( write_empty( f, RESERVED_SECTORS - 2 ) ) goto FailWrite;
if ( write_sector( f, s_fat_head ) ) goto FailWrite;
if ( write_empty( f, sectors_per_fat-1 ) ) goto FailWrite;
if ( write_sector( f, s_fat_head ) ) goto FailWrite;
if ( write_empty( f, sectors_per_fat-1 ) ) goto FailWrite;
if ( write_empty( f, sectors_per_disk - RESERVED_SECTORS - 2*sectors_per_fat ) ) goto FailWrite;
fclose(f);
return 0;
FailWrite:
fprintf(stderr, "could not write to '%s', aborting...\n", argv[2] );
unlink( argv[2] );
fclose(f);
return 1;
}

View File

@@ -1,16 +0,0 @@
# Copyright 2008 The Android Open Source Project
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
qemud.c
LOCAL_SHARED_LIBRARIES := \
libcutils \
LOCAL_MODULE:= qemud
LOCAL_MODULE_TAGS := debug
include $(BUILD_EXECUTABLE)

File diff suppressed because it is too large Load Diff

View File

@@ -1,157 +0,0 @@
#
# Copyright 2006 The Android Open Source Project
#
# Java method trace dump tool
#
LOCAL_PATH:= $(call my-dir)
common_includes := external/qemu
common_cflags := -O0 -g
include $(CLEAR_VARS)
LOCAL_SRC_FILES := post_trace.cpp trace_reader.cpp decoder.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := post_trace
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := read_trace.cpp trace_reader.cpp decoder.cpp armdis.cpp \
thumbdis.cpp opcode.cpp read_elf.cpp parse_options.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := read_trace
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := check_trace.cpp trace_reader.cpp decoder.cpp \
opcode.cpp read_elf.cpp parse_options.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := check_trace
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := bb_dump.cpp trace_reader.cpp decoder.cpp \
read_elf.cpp parse_options.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := bb_dump
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := bb2sym.cpp trace_reader.cpp decoder.cpp \
read_elf.cpp parse_options.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := bb2sym
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := profile_trace.cpp trace_reader.cpp decoder.cpp \
opcode.cpp read_elf.cpp parse_options.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := profile_trace
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := bbprof.cpp trace_reader.cpp decoder.cpp armdis.cpp \
thumbdis.cpp opcode.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := bbprof
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := q2g.cpp trace_reader.cpp decoder.cpp \
opcode.cpp read_elf.cpp parse_options.cpp gtrace.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := q2g
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := q2dm.cpp trace_reader.cpp decoder.cpp armdis.cpp \
thumbdis.cpp opcode.cpp read_elf.cpp parse_options.cpp dmtrace.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := q2dm
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := coverage.cpp trace_reader.cpp decoder.cpp armdis.cpp \
thumbdis.cpp opcode.cpp read_elf.cpp parse_options.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := coverage
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := stack_dump.cpp trace_reader.cpp decoder.cpp armdis.cpp \
thumbdis.cpp opcode.cpp read_elf.cpp parse_options.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := stack_dump
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := check_stack.cpp trace_reader.cpp decoder.cpp armdis.cpp \
thumbdis.cpp opcode.cpp read_elf.cpp parse_options.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := check_stack
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := hist_trace.cpp trace_reader.cpp decoder.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := hist_trace
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := read_addr.cpp trace_reader.cpp decoder.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := read_addr
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := read_pid.cpp trace_reader.cpp decoder.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := read_pid
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := exc_dump.cpp trace_reader.cpp decoder.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := exc_dump
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := read_method.cpp trace_reader.cpp decoder.cpp \
read_elf.cpp parse_options.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := read_method
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := profile_pid.cpp trace_reader.cpp decoder.cpp \
read_elf.cpp parse_options.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := profile_pid
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := dump_regions.cpp trace_reader.cpp decoder.cpp \
read_elf.cpp parse_options.cpp
LOCAL_C_INCLUDES += $(common_includes)
LOCAL_CFLAGS += $(common_cflags)
LOCAL_MODULE := dump_regions
include $(BUILD_HOST_EXECUTABLE)

View File

@@ -1,905 +0,0 @@
// Copyright 2006 The Android Open Source Project
#include <stdio.h>
#include <string.h>
#include "armdis.h"
#include "opcode.h"
static const char *cond_names[] = {
"eq",
"ne",
"cs",
"cc",
"mi",
"pl",
"vs",
"vc",
"hi",
"ls",
"ge",
"lt",
"gt",
"le",
"",
"RESERVED"
};
// Indexed by the shift type (bits 6-5)
static const char *shift_names[] = {
"LSL",
"LSR",
"ASR",
"ROR"
};
static const char* cond_to_str(int cond) {
return cond_names[cond];
}
char *Arm::disasm(uint32_t addr, uint32_t insn, char *result)
{
static char buf[80];
char *ptr;
ptr = result ? result : buf;
Opcode opcode = decode(insn);
switch (opcode) {
case OP_INVALID:
sprintf(ptr, "Invalid");
return ptr;
case OP_UNDEFINED:
sprintf(ptr, "Undefined");
return ptr;
case OP_ADC:
case OP_ADD:
case OP_AND:
case OP_BIC:
case OP_CMN:
case OP_CMP:
case OP_EOR:
case OP_MOV:
case OP_MVN:
case OP_ORR:
case OP_RSB:
case OP_RSC:
case OP_SBC:
case OP_SUB:
case OP_TEQ:
case OP_TST:
return disasm_alu(opcode, insn, ptr);
case OP_B:
case OP_BL:
return disasm_branch(addr, opcode, insn, ptr);
case OP_BKPT:
return disasm_bkpt(insn, ptr);
case OP_BLX:
// not supported yet
break;
case OP_BX:
return disasm_bx(insn, ptr);
case OP_CDP:
sprintf(ptr, "cdp");
return ptr;
case OP_CLZ:
return disasm_clz(insn, ptr);
case OP_LDC:
sprintf(ptr, "ldc");
return ptr;
case OP_LDM:
case OP_STM:
return disasm_memblock(opcode, insn, ptr);
case OP_LDR:
case OP_LDRB:
case OP_LDRBT:
case OP_LDRT:
case OP_STR:
case OP_STRB:
case OP_STRBT:
case OP_STRT:
return disasm_mem(insn, ptr);
case OP_LDRH:
case OP_LDRSB:
case OP_LDRSH:
case OP_STRH:
return disasm_memhalf(insn, ptr);
case OP_MCR:
case OP_MRC:
return disasm_mcr(opcode, insn, ptr);
case OP_MLA:
return disasm_mla(opcode, insn, ptr);
case OP_MRS:
return disasm_mrs(insn, ptr);
case OP_MSR:
return disasm_msr(insn, ptr);
case OP_MUL:
return disasm_mul(opcode, insn, ptr);
case OP_PLD:
return disasm_pld(insn, ptr);
case OP_STC:
sprintf(ptr, "stc");
return ptr;
case OP_SWI:
return disasm_swi(insn, ptr);
case OP_SWP:
case OP_SWPB:
return disasm_swp(opcode, insn, ptr);
case OP_UMLAL:
case OP_UMULL:
case OP_SMLAL:
case OP_SMULL:
return disasm_umlal(opcode, insn, ptr);
default:
sprintf(ptr, "Error");
return ptr;
}
return NULL;
}
char *Arm::disasm_alu(Opcode opcode, uint32_t insn, char *ptr)
{
static const uint8_t kNoOperand1 = 1;
static const uint8_t kNoDest = 2;
static const uint8_t kNoSbit = 4;
char rn_str[20];
char rd_str[20];
uint8_t flags = 0;
uint8_t cond = (insn >> 28) & 0xf;
uint8_t is_immed = (insn >> 25) & 0x1;
uint8_t bit_s = (insn >> 20) & 1;
uint8_t rn = (insn >> 16) & 0xf;
uint8_t rd = (insn >> 12) & 0xf;
uint8_t immed = insn & 0xff;
const char *opname = opcode_names[opcode];
switch (opcode) {
case OP_CMN:
case OP_CMP:
case OP_TEQ:
case OP_TST:
flags = kNoDest | kNoSbit;
break;
case OP_MOV:
case OP_MVN:
flags = kNoOperand1;
break;
default:
break;
}
// The "mov" instruction ignores the first operand (rn).
rn_str[0] = 0;
if ((flags & kNoOperand1) == 0) {
sprintf(rn_str, "r%d, ", rn);
}
// The following instructions do not write the result register (rd):
// tst, teq, cmp, cmn.
rd_str[0] = 0;
if ((flags & kNoDest) == 0) {
sprintf(rd_str, "r%d, ", rd);
}
const char *sbit_str = "";
if (bit_s && !(flags & kNoSbit))
sbit_str = "s";
if (is_immed) {
sprintf(ptr, "%s%s%s\t%s%s#%u ; 0x%x",
opname, cond_to_str(cond), sbit_str, rd_str, rn_str, immed, immed);
return ptr;
}
uint8_t shift_is_reg = (insn >> 4) & 1;
uint8_t rotate = (insn >> 8) & 0xf;
uint8_t rm = insn & 0xf;
uint8_t shift_type = (insn >> 5) & 0x3;
uint8_t rs = (insn >> 8) & 0xf;
uint8_t shift_amount = (insn >> 7) & 0x1f;
uint32_t rotated_val = immed;
uint8_t rotate2 = rotate << 1;
rotated_val = (rotated_val >> rotate2) | (rotated_val << (32 - rotate2));
if (!shift_is_reg && shift_type == 0 && shift_amount == 0) {
sprintf(ptr, "%s%s%s\t%s%sr%d",
opname, cond_to_str(cond), sbit_str, rd_str, rn_str, rm);
return ptr;
}
const char *shift_name = shift_names[shift_type];
if (shift_is_reg) {
sprintf(ptr, "%s%s%s\t%s%sr%d, %s r%d",
opname, cond_to_str(cond), sbit_str, rd_str, rn_str, rm,
shift_name, rs);
return ptr;
}
if (shift_amount == 0) {
if (shift_type == 3) {
sprintf(ptr, "%s%s%s\t%s%sr%d, RRX",
opname, cond_to_str(cond), sbit_str, rd_str, rn_str, rm);
return ptr;
}
shift_amount = 32;
}
sprintf(ptr, "%s%s%s\t%s%sr%d, %s #%u",
opname, cond_to_str(cond), sbit_str, rd_str, rn_str, rm,
shift_name, shift_amount);
return ptr;
}
char *Arm::disasm_branch(uint32_t addr, Opcode opcode, uint32_t insn, char *ptr)
{
uint8_t cond = (insn >> 28) & 0xf;
uint32_t offset = insn & 0xffffff;
// Sign-extend the 24-bit offset
if ((offset >> 23) & 1)
offset |= 0xff000000;
// Pre-compute the left-shift and the prefetch offset
offset <<= 2;
offset += 8;
addr += offset;
const char *opname = opcode_names[opcode];
sprintf(ptr, "%s%s\t0x%x", opname, cond_to_str(cond), addr);
return ptr;
}
char *Arm::disasm_bx(uint32_t insn, char *ptr)
{
uint8_t cond = (insn >> 28) & 0xf;
uint8_t rn = insn & 0xf;
sprintf(ptr, "bx%s\tr%d", cond_to_str(cond), rn);
return ptr;
}
char *Arm::disasm_bkpt(uint32_t insn, char *ptr)
{
uint32_t immed = (((insn >> 8) & 0xfff) << 4) | (insn & 0xf);
sprintf(ptr, "bkpt\t#%d", immed);
return ptr;
}
char *Arm::disasm_clz(uint32_t insn, char *ptr)
{
uint8_t cond = (insn >> 28) & 0xf;
uint8_t rd = (insn >> 12) & 0xf;
uint8_t rm = insn & 0xf;
sprintf(ptr, "clz%s\tr%d, r%d", cond_to_str(cond), rd, rm);
return ptr;
}
char *Arm::disasm_memblock(Opcode opcode, uint32_t insn, char *ptr)
{
char tmp_reg[10], tmp_list[80];
uint8_t cond = (insn >> 28) & 0xf;
uint8_t write_back = (insn >> 21) & 0x1;
uint8_t bit_s = (insn >> 22) & 0x1;
uint8_t is_up = (insn >> 23) & 0x1;
uint8_t is_pre = (insn >> 24) & 0x1;
uint8_t rn = (insn >> 16) & 0xf;
uint16_t reg_list = insn & 0xffff;
const char *opname = opcode_names[opcode];
const char *bang = "";
if (write_back)
bang = "!";
const char *carret = "";
if (bit_s)
carret = "^";
const char *comma = "";
tmp_list[0] = 0;
for (int ii = 0; ii < 16; ++ii) {
if (reg_list & (1 << ii)) {
sprintf(tmp_reg, "%sr%d", comma, ii);
strcat(tmp_list, tmp_reg);
comma = ",";
}
}
const char *addr_mode = "";
if (is_pre) {
if (is_up) {
addr_mode = "ib";
} else {
addr_mode = "db";
}
} else {
if (is_up) {
addr_mode = "ia";
} else {
addr_mode = "da";
}
}
sprintf(ptr, "%s%s%s\tr%d%s, {%s}%s",
opname, cond_to_str(cond), addr_mode, rn, bang, tmp_list, carret);
return ptr;
}
char *Arm::disasm_mem(uint32_t insn, char *ptr)
{
uint8_t cond = (insn >> 28) & 0xf;
uint8_t is_reg = (insn >> 25) & 0x1;
uint8_t is_load = (insn >> 20) & 0x1;
uint8_t write_back = (insn >> 21) & 0x1;
uint8_t is_byte = (insn >> 22) & 0x1;
uint8_t is_up = (insn >> 23) & 0x1;
uint8_t is_pre = (insn >> 24) & 0x1;
uint8_t rn = (insn >> 16) & 0xf;
uint8_t rd = (insn >> 12) & 0xf;
uint16_t offset = insn & 0xfff;
const char *opname = "ldr";
if (!is_load)
opname = "str";
const char *bang = "";
if (write_back)
bang = "!";
const char *minus = "";
if (is_up == 0)
minus = "-";
const char *byte = "";
if (is_byte)
byte = "b";
if (is_reg == 0) {
if (is_pre) {
if (offset == 0) {
sprintf(ptr, "%s%s%s\tr%d, [r%d]",
opname, cond_to_str(cond), byte, rd, rn);
} else {
sprintf(ptr, "%s%s%s\tr%d, [r%d, #%s%u]%s",
opname, cond_to_str(cond), byte, rd, rn, minus, offset, bang);
}
} else {
const char *transfer = "";
if (write_back)
transfer = "t";
sprintf(ptr, "%s%s%s%s\tr%d, [r%d], #%s%u",
opname, cond_to_str(cond), byte, transfer, rd, rn, minus, offset);
}
return ptr;
}
uint8_t rm = insn & 0xf;
uint8_t shift_type = (insn >> 5) & 0x3;
uint8_t shift_amount = (insn >> 7) & 0x1f;
const char *shift_name = shift_names[shift_type];
if (is_pre) {
if (shift_amount == 0) {
if (shift_type == 0) {
sprintf(ptr, "%s%s%s\tr%d, [r%d, %sr%d]%s",
opname, cond_to_str(cond), byte, rd, rn, minus, rm, bang);
return ptr;
}
if (shift_type == 3) {
sprintf(ptr, "%s%s%s\tr%d, [r%d, %sr%d, RRX]%s",
opname, cond_to_str(cond), byte, rd, rn, minus, rm, bang);
return ptr;
}
shift_amount = 32;
}
sprintf(ptr, "%s%s%s\tr%d, [r%d, %sr%d, %s #%u]%s",
opname, cond_to_str(cond), byte, rd, rn, minus, rm,
shift_name, shift_amount, bang);
return ptr;
}
const char *transfer = "";
if (write_back)
transfer = "t";
if (shift_amount == 0) {
if (shift_type == 0) {
sprintf(ptr, "%s%s%s%s\tr%d, [r%d], %sr%d",
opname, cond_to_str(cond), byte, transfer, rd, rn, minus, rm);
return ptr;
}
if (shift_type == 3) {
sprintf(ptr, "%s%s%s%s\tr%d, [r%d], %sr%d, RRX",
opname, cond_to_str(cond), byte, transfer, rd, rn, minus, rm);
return ptr;
}
shift_amount = 32;
}
sprintf(ptr, "%s%s%s%s\tr%d, [r%d], %sr%d, %s #%u",
opname, cond_to_str(cond), byte, transfer, rd, rn, minus, rm,
shift_name, shift_amount);
return ptr;
}
char *Arm::disasm_memhalf(uint32_t insn, char *ptr)
{
uint8_t cond = (insn >> 28) & 0xf;
uint8_t is_load = (insn >> 20) & 0x1;
uint8_t write_back = (insn >> 21) & 0x1;
uint8_t is_immed = (insn >> 22) & 0x1;
uint8_t is_up = (insn >> 23) & 0x1;
uint8_t is_pre = (insn >> 24) & 0x1;
uint8_t rn = (insn >> 16) & 0xf;
uint8_t rd = (insn >> 12) & 0xf;
uint8_t bits_65 = (insn >> 5) & 0x3;
uint8_t rm = insn & 0xf;
uint8_t offset = (((insn >> 8) & 0xf) << 4) | (insn & 0xf);
const char *opname = "ldr";
if (is_load == 0)
opname = "str";
const char *width = "";
if (bits_65 == 1)
width = "h";
else if (bits_65 == 2)
width = "sb";
else
width = "sh";
const char *bang = "";
if (write_back)
bang = "!";
const char *minus = "";
if (is_up == 0)
minus = "-";
if (is_immed) {
if (is_pre) {
if (offset == 0) {
sprintf(ptr, "%s%sh\tr%d, [r%d]", opname, cond_to_str(cond), rd, rn);
} else {
sprintf(ptr, "%s%sh\tr%d, [r%d, #%s%u]%s",
opname, cond_to_str(cond), rd, rn, minus, offset, bang);
}
} else {
sprintf(ptr, "%s%sh\tr%d, [r%d], #%s%u",
opname, cond_to_str(cond), rd, rn, minus, offset);
}
return ptr;
}
if (is_pre) {
sprintf(ptr, "%s%sh\tr%d, [r%d, %sr%d]%s",
opname, cond_to_str(cond), rd, rn, minus, rm, bang);
} else {
sprintf(ptr, "%s%sh\tr%d, [r%d], %sr%d",
opname, cond_to_str(cond), rd, rn, minus, rm);
}
return ptr;
}
char *Arm::disasm_mcr(Opcode opcode, uint32_t insn, char *ptr)
{
uint8_t cond = (insn >> 28) & 0xf;
uint8_t crn = (insn >> 16) & 0xf;
uint8_t crd = (insn >> 12) & 0xf;
uint8_t cpnum = (insn >> 8) & 0xf;
uint8_t opcode2 = (insn >> 5) & 0x7;
uint8_t crm = insn & 0xf;
const char *opname = opcode_names[opcode];
sprintf(ptr, "%s%s\t%d, 0, r%d, cr%d, cr%d, {%d}",
opname, cond_to_str(cond), cpnum, crd, crn, crm, opcode2);
return ptr;
}
char *Arm::disasm_mla(Opcode opcode, uint32_t insn, char *ptr)
{
uint8_t cond = (insn >> 28) & 0xf;
uint8_t rd = (insn >> 16) & 0xf;
uint8_t rn = (insn >> 12) & 0xf;
uint8_t rs = (insn >> 8) & 0xf;
uint8_t rm = insn & 0xf;
uint8_t bit_s = (insn >> 20) & 1;
const char *opname = opcode_names[opcode];
sprintf(ptr, "%s%s%s\tr%d, r%d, r%d, r%d",
opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs, rn);
return ptr;
}
char *Arm::disasm_umlal(Opcode opcode, uint32_t insn, char *ptr)
{
uint8_t cond = (insn >> 28) & 0xf;
uint8_t rdhi = (insn >> 16) & 0xf;
uint8_t rdlo = (insn >> 12) & 0xf;
uint8_t rs = (insn >> 8) & 0xf;
uint8_t rm = insn & 0xf;
uint8_t bit_s = (insn >> 20) & 1;
const char *opname = opcode_names[opcode];
sprintf(ptr, "%s%s%s\tr%d, r%d, r%d, r%d",
opname, cond_to_str(cond), bit_s ? "s" : "", rdlo, rdhi, rm, rs);
return ptr;
}
char *Arm::disasm_mul(Opcode opcode, uint32_t insn, char *ptr)
{
uint8_t cond = (insn >> 28) & 0xf;
uint8_t rd = (insn >> 16) & 0xf;
uint8_t rs = (insn >> 8) & 0xf;
uint8_t rm = insn & 0xf;
uint8_t bit_s = (insn >> 20) & 1;
const char *opname = opcode_names[opcode];
sprintf(ptr, "%s%s%s\tr%d, r%d, r%d",
opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs);
return ptr;
}
char *Arm::disasm_mrs(uint32_t insn, char *ptr)
{
uint8_t cond = (insn >> 28) & 0xf;
uint8_t rd = (insn >> 12) & 0xf;
uint8_t ps = (insn >> 22) & 1;
sprintf(ptr, "mrs%s\tr%d, %s", cond_to_str(cond), rd, ps ? "spsr" : "cpsr");
return ptr;
}
char *Arm::disasm_msr(uint32_t insn, char *ptr)
{
char flags[8];
int flag_index = 0;
uint8_t cond = (insn >> 28) & 0xf;
uint8_t is_immed = (insn >> 25) & 0x1;
uint8_t pd = (insn >> 22) & 1;
uint8_t mask = (insn >> 16) & 0xf;
if (mask & 1)
flags[flag_index++] = 'c';
if (mask & 2)
flags[flag_index++] = 'x';
if (mask & 4)
flags[flag_index++] = 's';
if (mask & 8)
flags[flag_index++] = 'f';
flags[flag_index] = 0;
if (is_immed) {
uint32_t immed = insn & 0xff;
uint8_t rotate = (insn >> 8) & 0xf;
uint8_t rotate2 = rotate << 1;
uint32_t rotated_val = (immed >> rotate2) | (immed << (32 - rotate2));
sprintf(ptr, "msr%s\t%s_%s, #0x%x",
cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rotated_val);
return ptr;
}
uint8_t rm = insn & 0xf;
sprintf(ptr, "msr%s\t%s_%s, r%d",
cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rm);
return ptr;
}
char *Arm::disasm_pld(uint32_t insn, char *ptr)
{
uint8_t is_reg = (insn >> 25) & 0x1;
uint8_t is_up = (insn >> 23) & 0x1;
uint8_t rn = (insn >> 16) & 0xf;
const char *minus = "";
if (is_up == 0)
minus = "-";
if (is_reg) {
uint8_t rm = insn & 0xf;
sprintf(ptr, "pld\t[r%d, %sr%d]", rn, minus, rm);
return ptr;
}
uint16_t offset = insn & 0xfff;
if (offset == 0) {
sprintf(ptr, "pld\t[r%d]", rn);
} else {
sprintf(ptr, "pld\t[r%d, #%s%u]", rn, minus, offset);
}
return ptr;
}
char *Arm::disasm_swi(uint32_t insn, char *ptr)
{
uint8_t cond = (insn >> 28) & 0xf;
uint32_t sysnum = insn & 0x00ffffff;
sprintf(ptr, "swi%s 0x%x", cond_to_str(cond), sysnum);
return ptr;
}
char *Arm::disasm_swp(Opcode opcode, uint32_t insn, char *ptr)
{
uint8_t cond = (insn >> 28) & 0xf;
uint8_t rn = (insn >> 16) & 0xf;
uint8_t rd = (insn >> 12) & 0xf;
uint8_t rm = insn & 0xf;
const char *opname = opcode_names[opcode];
sprintf(ptr, "%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn);
return ptr;
}
Opcode Arm::decode(uint32_t insn) {
uint32_t bits27_26 = (insn >> 26) & 0x3;
switch (bits27_26) {
case 0x0:
return decode00(insn);
case 0x1:
return decode01(insn);
case 0x2:
return decode10(insn);
case 0x3:
return decode11(insn);
}
return OP_INVALID;
}
Opcode Arm::decode00(uint32_t insn) {
uint8_t bit25 = (insn >> 25) & 0x1;
uint8_t bit4 = (insn >> 4) & 0x1;
if (bit25 == 0 && bit4 == 1) {
if ((insn & 0x0ffffff0) == 0x012fff10) {
// Bx instruction
return OP_BX;
}
if ((insn & 0x0ff000f0) == 0x01600010) {
// Clz instruction
return OP_CLZ;
}
if ((insn & 0xfff000f0) == 0xe1200070) {
// Bkpt instruction
return OP_BKPT;
}
uint32_t bits7_4 = (insn >> 4) & 0xf;
if (bits7_4 == 0x9) {
if ((insn & 0x0ff00ff0) == 0x01000090) {
// Swp instruction
uint8_t bit22 = (insn >> 22) & 0x1;
if (bit22)
return OP_SWPB;
return OP_SWP;
}
// One of the multiply instructions
return decode_mul(insn);
}
uint8_t bit7 = (insn >> 7) & 0x1;
if (bit7 == 1) {
// One of the load/store halfword/byte instructions
return decode_ldrh(insn);
}
}
// One of the data processing instructions
return decode_alu(insn);
}
Opcode Arm::decode01(uint32_t insn) {
uint8_t is_reg = (insn >> 25) & 0x1;
uint8_t bit4 = (insn >> 4) & 0x1;
if (is_reg == 1 && bit4 == 1)
return OP_UNDEFINED;
uint8_t is_load = (insn >> 20) & 0x1;
uint8_t is_byte = (insn >> 22) & 0x1;
if ((insn & 0xfd70f000) == 0xf550f000) {
// Pre-load
return OP_PLD;
}
if (is_load) {
if (is_byte) {
// Load byte
return OP_LDRB;
}
// Load word
return OP_LDR;
}
if (is_byte) {
// Store byte
return OP_STRB;
}
// Store word
return OP_STR;
}
Opcode Arm::decode10(uint32_t insn) {
uint8_t bit25 = (insn >> 25) & 0x1;
if (bit25 == 0) {
// LDM/STM
uint8_t is_load = (insn >> 20) & 0x1;
if (is_load)
return OP_LDM;
return OP_STM;
}
// Branch or Branch with link
uint8_t is_link = (insn >> 24) & 1;
uint32_t offset = insn & 0xffffff;
// Sign-extend the 24-bit offset
if ((offset >> 23) & 1)
offset |= 0xff000000;
// Pre-compute the left-shift and the prefetch offset
offset <<= 2;
offset += 8;
if (is_link == 0)
return OP_B;
return OP_BL;
}
Opcode Arm::decode11(uint32_t insn) {
uint8_t bit25 = (insn >> 25) & 0x1;
if (bit25 == 0) {
// LDC, SDC
uint8_t is_load = (insn >> 20) & 0x1;
if (is_load) {
// LDC
return OP_LDC;
}
// STC
return OP_STC;
}
uint8_t bit24 = (insn >> 24) & 0x1;
if (bit24 == 0x1) {
// SWI
return OP_SWI;
}
uint8_t bit4 = (insn >> 4) & 0x1;
uint8_t cpnum = (insn >> 8) & 0xf;
if (cpnum == 15) {
// Special case for coprocessor 15
uint8_t opcode = (insn >> 21) & 0x7;
if (bit4 == 0 || opcode != 0) {
// This is an unexpected bit pattern. Create an undefined
// instruction in case this is ever executed.
return OP_UNDEFINED;
}
// MRC, MCR
uint8_t is_mrc = (insn >> 20) & 0x1;
if (is_mrc)
return OP_MRC;
return OP_MCR;
}
if (bit4 == 0) {
// CDP
return OP_CDP;
}
// MRC, MCR
uint8_t is_mrc = (insn >> 20) & 0x1;
if (is_mrc)
return OP_MRC;
return OP_MCR;
}
Opcode Arm::decode_mul(uint32_t insn) {
uint8_t bit24 = (insn >> 24) & 0x1;
if (bit24 != 0) {
// This is an unexpected bit pattern. Create an undefined
// instruction in case this is ever executed.
return OP_UNDEFINED;
}
uint8_t bit23 = (insn >> 23) & 0x1;
uint8_t bit22_U = (insn >> 22) & 0x1;
uint8_t bit21_A = (insn >> 21) & 0x1;
if (bit23 == 0) {
// 32-bit multiply
if (bit22_U != 0) {
// This is an unexpected bit pattern. Create an undefined
// instruction in case this is ever executed.
return OP_UNDEFINED;
}
if (bit21_A == 0)
return OP_MUL;
return OP_MLA;
}
// 64-bit multiply
if (bit22_U == 0) {
// Unsigned multiply long
if (bit21_A == 0)
return OP_UMULL;
return OP_UMLAL;
}
// Signed multiply long
if (bit21_A == 0)
return OP_SMULL;
return OP_SMLAL;
}
Opcode Arm::decode_ldrh(uint32_t insn) {
uint8_t is_load = (insn >> 20) & 0x1;
uint8_t bits_65 = (insn >> 5) & 0x3;
if (is_load) {
if (bits_65 == 0x1) {
// Load unsigned halfword
return OP_LDRH;
} else if (bits_65 == 0x2) {
// Load signed byte
return OP_LDRSB;
}
// Signed halfword
if (bits_65 != 0x3) {
// This is an unexpected bit pattern. Create an undefined
// instruction in case this is ever executed.
return OP_UNDEFINED;
}
// Load signed halfword
return OP_LDRSH;
}
// Store halfword
if (bits_65 != 0x1) {
// This is an unexpected bit pattern. Create an undefined
// instruction in case this is ever executed.
return OP_UNDEFINED;
}
// Store halfword
return OP_STRH;
}
Opcode Arm::decode_alu(uint32_t insn) {
uint8_t is_immed = (insn >> 25) & 0x1;
uint8_t opcode = (insn >> 21) & 0xf;
uint8_t bit_s = (insn >> 20) & 1;
uint8_t shift_is_reg = (insn >> 4) & 1;
uint8_t bit7 = (insn >> 7) & 1;
if (!is_immed && shift_is_reg && (bit7 != 0)) {
// This is an unexpected bit pattern. Create an undefined
// instruction in case this is ever executed.
return OP_UNDEFINED;
}
switch (opcode) {
case 0x0:
return OP_AND;
case 0x1:
return OP_EOR;
case 0x2:
return OP_SUB;
case 0x3:
return OP_RSB;
case 0x4:
return OP_ADD;
case 0x5:
return OP_ADC;
case 0x6:
return OP_SBC;
case 0x7:
return OP_RSC;
case 0x8:
if (bit_s)
return OP_TST;
return OP_MRS;
case 0x9:
if (bit_s)
return OP_TEQ;
return OP_MSR;
case 0xa:
if (bit_s)
return OP_CMP;
return OP_MRS;
case 0xb:
if (bit_s)
return OP_CMN;
return OP_MSR;
case 0xc:
return OP_ORR;
case 0xd:
return OP_MOV;
case 0xe:
return OP_BIC;
case 0xf:
return OP_MVN;
}
// Unreachable
return OP_INVALID;
}

View File

@@ -1,45 +0,0 @@
// Copyright 2006 The Android Open Source Project
#ifndef ARMDIS_H
#define ARMDIS_H
#include <inttypes.h>
#include "opcode.h"
class Arm {
public:
static char *disasm(uint32_t addr, uint32_t insn, char *buffer);
static Opcode decode(uint32_t insn);
private:
static Opcode decode00(uint32_t insn);
static Opcode decode01(uint32_t insn);
static Opcode decode10(uint32_t insn);
static Opcode decode11(uint32_t insn);
static Opcode decode_mul(uint32_t insn);
static Opcode decode_ldrh(uint32_t insn);
static Opcode decode_alu(uint32_t insn);
static char *disasm_alu(Opcode opcode, uint32_t insn, char *ptr);
static char *disasm_branch(uint32_t addr, Opcode opcode, uint32_t insn, char *ptr);
static char *disasm_bx(uint32_t insn, char *ptr);
static char *disasm_bkpt(uint32_t insn, char *ptr);
static char *disasm_clz(uint32_t insn, char *ptr);
static char *disasm_memblock(Opcode opcode, uint32_t insn, char *ptr);
static char *disasm_mem(uint32_t insn, char *ptr);
static char *disasm_memhalf(uint32_t insn, char *ptr);
static char *disasm_mcr(Opcode opcode, uint32_t insn, char *ptr);
static char *disasm_mla(Opcode opcode, uint32_t insn, char *ptr);
static char *disasm_umlal(Opcode opcode, uint32_t insn, char *ptr);
static char *disasm_mul(Opcode opcode, uint32_t insn, char *ptr);
static char *disasm_mrs(uint32_t insn, char *ptr);
static char *disasm_msr(uint32_t insn, char *ptr);
static char *disasm_pld(uint32_t insn, char *ptr);
static char *disasm_swi(uint32_t insn, char *ptr);
static char *disasm_swp(Opcode opcode, uint32_t insn, char *ptr);
};
extern char *disasm_insn_thumb(uint32_t pc, uint32_t insn1, uint32_t insn2, char *result);
extern Opcode decode_insn_thumb(uint32_t given);
#endif /* ARMDIS_H */

View File

@@ -1,140 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
#include <assert.h>
#include "trace_reader.h"
#include "parse_options.h"
typedef TraceReader<> TraceReaderType;
#include "parse_options-inl.h"
struct MyStaticRec {
StaticRec bb;
symbol_type *sym;
MyStaticRec *inner; // pointer to an inner basic block
int is_thumb;
};
MyStaticRec **assign_inner_blocks(int num_blocks, MyStaticRec *blocks);
void Usage(const char *program)
{
fprintf(stderr, "Usage: %s [options] trace_file elf_file\n", program);
OptionsUsage();
}
// This function is called from quicksort to compare addresses of basic
// blocks.
int cmp_inc_addr(const void *a, const void *b) {
MyStaticRec *bb1, *bb2;
bb1 = *(MyStaticRec**)a;
bb2 = *(MyStaticRec**)b;
if (bb1->bb.bb_addr < bb2->bb.bb_addr)
return -1;
if (bb1->bb.bb_addr > bb2->bb.bb_addr)
return 1;
return bb1->bb.bb_num - bb2->bb.bb_num;
}
int main(int argc, char **argv) {
uint32_t insns[kMaxInsnPerBB];
// Parse the options
ParseOptions(argc, argv);
if (argc - optind != 2) {
Usage(argv[0]);
exit(1);
}
char *trace_filename = argv[optind++];
char *elf_file = argv[optind++];
TraceReader<> *trace = new TraceReader<>;
trace->Open(trace_filename);
trace->ReadKernelSymbols(elf_file);
trace->SetRoot(root);
TraceHeader *header = trace->GetHeader();
uint32_t num_static_bb = header->num_static_bb;
// Allocate space for all of the static blocks
MyStaticRec *blocks = new MyStaticRec[num_static_bb];
// Read in all the static blocks
for (uint32_t ii = 0; ii < num_static_bb; ++ii) {
trace->ReadStatic(&blocks[ii].bb);
blocks[ii].is_thumb = blocks[ii].bb.bb_addr & 1;
blocks[ii].bb.bb_addr &= ~1;
blocks[ii].sym = NULL;
blocks[ii].inner = NULL;
trace->ReadStaticInsns(blocks[ii].bb.num_insns, insns);
}
MyStaticRec **sorted = assign_inner_blocks(num_static_bb, blocks);
while (1) {
symbol_type *sym;
BBEvent event;
BBEvent ignored;
if (GetNextValidEvent(trace, &event, &ignored, &sym))
break;
uint64_t bb_num = event.bb_num;
blocks[bb_num].sym = sym;
}
printf("# bb num_insns bb_addr file symbol\n");
for (uint32_t ii = 0; ii < num_static_bb; ++ii) {
if (sorted[ii]->bb.bb_addr == 0 || sorted[ii]->bb.num_insns == 0
|| sorted[ii]->sym == NULL)
continue;
printf("%8lld %3d 0x%08x %s %s\n",
sorted[ii]->bb.bb_num, sorted[ii]->bb.num_insns,
sorted[ii]->bb.bb_addr, sorted[ii]->sym->region->path,
sorted[ii]->sym->name);
}
return 0;
}
// Find the basic blocks that are subsets of other basic blocks.
MyStaticRec **assign_inner_blocks(int num_blocks, MyStaticRec *blocks)
{
int ii;
uint32_t addr_end, addr_diff;
// Create a list of pointers to the basic blocks that we can sort.
MyStaticRec **sorted = new MyStaticRec*[num_blocks];
for (ii = 0; ii < num_blocks; ++ii) {
sorted[ii] = &blocks[ii];
}
// Sort the basic blocks into increasing address order
qsort(sorted, num_blocks, sizeof(MyStaticRec*), cmp_inc_addr);
// Create pointers to inner blocks and break up the enclosing block
// so that there is no overlap.
for (ii = 0; ii < num_blocks - 1; ++ii) {
int num_bytes;
if (sorted[ii]->is_thumb)
num_bytes = sorted[ii]->bb.num_insns << 1;
else
num_bytes = sorted[ii]->bb.num_insns << 2;
addr_end = sorted[ii]->bb.bb_addr + num_bytes;
if (addr_end > sorted[ii + 1]->bb.bb_addr) {
sorted[ii]->inner = sorted[ii + 1];
addr_diff = sorted[ii + 1]->bb.bb_addr - sorted[ii]->bb.bb_addr;
uint32_t num_insns;
if (sorted[ii]->is_thumb)
num_insns = addr_diff >> 1;
else
num_insns = addr_diff >> 2;
sorted[ii]->bb.num_insns = num_insns;
}
}
return sorted;
}

View File

@@ -1,47 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
#include <assert.h>
#include "trace_reader.h"
#include "parse_options.h"
typedef TraceReader<> TraceReaderType;
#include "parse_options-inl.h"
void Usage(const char *program)
{
fprintf(stderr, "Usage: %s [options] trace_file elf_file\n", program);
OptionsUsage();
}
int main(int argc, char **argv) {
// Parse the options
ParseOptions(argc, argv);
if (argc - optind != 2) {
Usage(argv[0]);
exit(1);
}
char *trace_filename = argv[optind++];
char *elf_file = argv[optind++];
TraceReader<> *trace = new TraceReader<>;
trace->Open(trace_filename);
trace->ReadKernelSymbols(elf_file);
trace->SetRoot(root);
printf("# time bb pid num_insns bb_addr\n");
while (1) {
symbol_type *sym;
BBEvent event;
BBEvent ignored;
if (GetNextValidEvent(trace, &event, &ignored, &sym))
break;
printf("%7lld %4lld %5d %3d 0x%08x %s\n",
event.time, event.bb_num, event.pid, event.num_insns,
event.bb_addr, sym->name);
}
return 0;
}

View File

@@ -1,222 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "trace_reader.h"
#include "armdis.h"
struct MyStaticRec {
StaticRec bb;
uint32_t *insns;
uint32_t *cycles; // number of cycles for each insn
uint32_t elapsed; // number of cycles for basic block
int freq; // execution frequency
MyStaticRec *inner; // pointer to an inner basic block
int is_thumb;
};
MyStaticRec **assign_inner_blocks(int num_blocks, MyStaticRec *blocks);
// This function is called from quicksort to compare addresses of basic
// blocks.
int cmp_inc_addr(const void *a, const void *b) {
MyStaticRec *bb1, *bb2;
bb1 = *(MyStaticRec**)a;
bb2 = *(MyStaticRec**)b;
if (bb1->bb.bb_addr < bb2->bb.bb_addr)
return -1;
if (bb1->bb.bb_addr > bb2->bb.bb_addr)
return 1;
return bb1->bb.bb_num - bb2->bb.bb_num;
}
// This function is called from quicksort to compare the elapsed time
// of basic blocks.
int cmp_dec_elapsed(const void *a, const void *b) {
MyStaticRec *bb1, *bb2;
bb1 = *(MyStaticRec**)a;
bb2 = *(MyStaticRec**)b;
if (bb1->elapsed < bb2->elapsed)
return 1;
if (bb1->elapsed > bb2->elapsed)
return -1;
return bb1->bb.bb_num - bb2->bb.bb_num;
}
// This function is called from quicksort to compare frequencies of
// basic blocks.
int cmp_dec_freq(const void *a, const void *b) {
MyStaticRec *bb1, *bb2;
bb1 = *(MyStaticRec**)a;
bb2 = *(MyStaticRec**)b;
if (bb1->freq < bb2->freq)
return 1;
if (bb1->freq > bb2->freq)
return -1;
return bb1->bb.bb_num - bb2->bb.bb_num;
}
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "Usage: %s trace_file\n", argv[0]);
exit(1);
}
char *trace_filename = argv[1];
TraceReaderBase *trace = new TraceReaderBase;
trace->Open(trace_filename);
TraceHeader *header = trace->GetHeader();
uint32_t num_static_bb = header->num_static_bb;
// Allocate space for all of the static blocks
MyStaticRec *blocks = new MyStaticRec[num_static_bb];
// Read in all the static blocks
for (uint32_t ii = 0; ii < num_static_bb; ++ii) {
trace->ReadStatic(&blocks[ii].bb);
blocks[ii].is_thumb = blocks[ii].bb.bb_addr & 1;
blocks[ii].bb.bb_addr &= ~1;
uint32_t num_insns = blocks[ii].bb.num_insns;
blocks[ii].insns = new uint32_t[num_insns];
blocks[ii].cycles = new uint32_t[num_insns];
memset(blocks[ii].cycles, 0, num_insns * sizeof(uint32_t));
trace->ReadStaticInsns(num_insns, blocks[ii].insns);
blocks[ii].elapsed = 0;
blocks[ii].freq = 0;
blocks[ii].inner = NULL;
}
MyStaticRec **sorted = assign_inner_blocks(num_static_bb, blocks);
uint32_t prev_time = 0;
uint32_t elapsed = 0;
uint32_t dummy;
uint32_t *cycle_ptr = &dummy;
uint32_t *bb_elapsed_ptr = &dummy;
while (1) {
BBEvent event;
if (trace->ReadBB(&event))
break;
// Assign frequencies to each basic block
uint64_t bb_num = event.bb_num;
int num_insns = event.num_insns;
blocks[bb_num].freq += 1;
for (MyStaticRec *bptr = blocks[bb_num].inner; bptr; bptr = bptr->inner)
bptr->freq += 1;
// Assign simulation time to each instruction
for (MyStaticRec *bptr = &blocks[bb_num]; bptr; bptr = bptr->inner) {
uint32_t bb_num_insns = bptr->bb.num_insns;
for (uint32_t ii = 0; num_insns && ii < bb_num_insns; ++ii, --num_insns) {
uint32_t sim_time = trace->ReadInsnTime(event.time);
elapsed = sim_time - prev_time;
prev_time = sim_time;
// Attribute the elapsed time to the previous instruction and
// basic block.
*cycle_ptr += elapsed;
*bb_elapsed_ptr += elapsed;
cycle_ptr = &bptr->cycles[ii];
bb_elapsed_ptr = &bptr->elapsed;
}
}
}
*cycle_ptr += 1;
*bb_elapsed_ptr += 1;
// Sort the basic blocks into decreasing elapsed time
qsort(sorted, num_static_bb, sizeof(MyStaticRec*), cmp_dec_elapsed);
char spaces[80];
memset(spaces, ' ', 79);
spaces[79] = 0;
for (uint32_t ii = 0; ii < num_static_bb; ++ii) {
printf("bb %lld addr: 0x%x, insns: %d freq: %u elapsed: %u\n",
sorted[ii]->bb.bb_num, sorted[ii]->bb.bb_addr,
sorted[ii]->bb.num_insns, sorted[ii]->freq,
sorted[ii]->elapsed);
int num_insns = sorted[ii]->bb.num_insns;
uint32_t addr = sorted[ii]->bb.bb_addr;
for (int jj = 0; jj < num_insns; ++jj) {
uint32_t elapsed = sorted[ii]->cycles[jj];
uint32_t insn = sorted[ii]->insns[jj];
if (insn_is_thumb(insn)) {
insn = insn_unwrap_thumb(insn);
// thumb_pair is true if this is the first of a pair of
// thumb instructions (BL or BLX).
bool thumb_pair = ((insn & 0xf800) == 0xf000);
// Get the next thumb instruction (if any) because we may need
// it for the case where insn is BL or BLX.
uint32_t insn2 = 0;
if (thumb_pair && (jj + 1 < num_insns)) {
insn2 = sorted[ii]->insns[jj + 1];
insn2 = insn_unwrap_thumb(insn2);
jj += 1;
}
char *disasm = disasm_insn_thumb(addr, insn, insn2, NULL);
if (thumb_pair) {
printf(" %4u %08x %04x %04x %s\n", elapsed, addr, insn,
insn2, disasm);
addr += 2;
} else {
printf(" %4u %08x %04x %s\n", elapsed, addr, insn,
disasm);
}
addr += 2;
} else {
char *disasm = Arm::disasm(addr, insn, NULL);
printf(" %4u %08x %08x %s\n", elapsed, addr, insn, disasm);
addr += 4;
}
}
}
delete[] sorted;
return 0;
}
// Find the basic blocks that are subsets of other basic blocks.
MyStaticRec **assign_inner_blocks(int num_blocks, MyStaticRec *blocks)
{
int ii;
uint32_t addr_end, addr_diff;
// Create a list of pointers to the basic blocks that we can sort.
MyStaticRec **sorted = new MyStaticRec*[num_blocks];
for (ii = 0; ii < num_blocks; ++ii) {
sorted[ii] = &blocks[ii];
}
// Sort the basic blocks into increasing address order
qsort(sorted, num_blocks, sizeof(MyStaticRec*), cmp_inc_addr);
// Create pointers to inner blocks and break up the enclosing block
// so that there is no overlap.
for (ii = 0; ii < num_blocks - 1; ++ii) {
int num_bytes;
if (sorted[ii]->is_thumb)
num_bytes = sorted[ii]->bb.num_insns << 1;
else
num_bytes = sorted[ii]->bb.num_insns << 2;
addr_end = sorted[ii]->bb.bb_addr + num_bytes;
if (addr_end > sorted[ii + 1]->bb.bb_addr) {
sorted[ii]->inner = sorted[ii + 1];
addr_diff = sorted[ii + 1]->bb.bb_addr - sorted[ii]->bb.bb_addr;
uint32_t num_insns;
if (sorted[ii]->is_thumb)
num_insns = addr_diff >> 1;
else
num_insns = addr_diff >> 2;
sorted[ii]->bb.num_insns = num_insns;
}
}
return sorted;
}

View File

@@ -1,40 +0,0 @@
// Copyright 2006 The Android Open Source Project
#ifndef BITVECTOR_H
#define BITVECTOR_H
#include <inttypes.h>
#include <assert.h>
class Bitvector {
public:
explicit Bitvector(int num_bits) {
num_bits_ = num_bits;
// Round up to a multiple of 32
num_bits = (num_bits + 31) & ~31;
vector_ = new uint32_t[num_bits >> 5];
}
~Bitvector() {
delete[] vector_;
}
void SetBit(int bitnum) {
assert(bitnum < num_bits_);
vector_[bitnum >> 5] |= 1 << (bitnum & 31);
}
void ClearBit(int bitnum) {
assert(bitnum < num_bits_);
vector_[bitnum >> 5] &= ~(1 << (bitnum & 31));
}
bool GetBit(int bitnum) {
assert(bitnum < num_bits_);
return (vector_[bitnum >> 5] >> (bitnum & 31)) & 1;
}
private:
int num_bits_;
uint32_t *vector_;
};
#endif // BITVECTOR_H

View File

@@ -1,775 +0,0 @@
// Copyright 2006 The Android Open Source Project
#ifndef CALL_STACK_H
#define CALL_STACK_H
#include "opcode.h"
#include "armdis.h"
class CallStackBase {
public:
int getId() { return mId; }
void setId(int id) { mId = id; }
private:
int mId;
};
// Define a template class for the stack frame. The template parameter
// SYM is the symbol_type from the TraceReader<> template class. To
// use the CallStack class, the user derives a subclass of StackFrame
// and defines push() and pop() methods. This derived class is then
// passed as a template parameter to CallStack.
template <class SYM>
class StackFrame {
public:
virtual ~StackFrame() {};
virtual void push(int stackLevel, uint64_t time, CallStackBase *base) {};
virtual void pop(int stackLevel, uint64_t time, CallStackBase *base) {};
typedef SYM symbol_type;
static const uint32_t kCausedException = 0x01;
static const uint32_t kInterpreted = 0x02;
static const uint32_t kStartNative = 0x04;
static const uint32_t kPopBarrier = (kCausedException | kInterpreted
| kStartNative);
symbol_type *function; // the symbol for the function we entered
uint32_t addr; // return address when this function returns
uint32_t flags;
uint32_t time; // for debugging when a problem occurred
uint32_t global_time; // for debugging when a problem occurred
};
template <class FRAME, class BASE = CallStackBase>
class CallStack : public BASE {
public:
typedef FRAME frame_type;
typedef typename FRAME::symbol_type symbol_type;
typedef typename FRAME::symbol_type::region_type region_type;
typedef BASE base_type;
CallStack(int id, int numFrames, TraceReaderType *trace);
~CallStack();
void updateStack(BBEvent *event, symbol_type *function);
void popAll(uint64_t time);
void threadStart(uint64_t time);
void threadStop(uint64_t time);
// Set to true if you don't want to see any Java methods ever
void setNativeOnly(bool nativeOnly) {
mNativeOnly = nativeOnly;
}
int getStackLevel() { return mTop; }
uint64_t getGlobalTime(uint64_t time) { return time + mSkippedTime; }
void showStack(FILE *stream);
int mNumFrames;
FRAME *mFrames;
int mTop; // index of the next stack frame to write
private:
enum Action { NONE, PUSH, POP, NATIVE_PUSH };
Action getAction(BBEvent *event, symbol_type *function);
void doMethodAction(BBEvent *event, symbol_type *function);
void doMethodPop(BBEvent *event, uint32_t addr, const uint32_t flags);
void doSimplePush(symbol_type *function, uint32_t addr,
uint64_t time, int flags);
void doSimplePop(uint64_t time);
void doPush(BBEvent *event, symbol_type *function);
void doPop(BBEvent *event, symbol_type *function, Action methodAction);
TraceReaderType *mTrace;
// This is a global switch that disables Java methods from appearing
// on the stack.
bool mNativeOnly;
// This keeps track of whether native frames are currently allowed on the
// stack.
bool mAllowNativeFrames;
symbol_type mDummyFunction;
region_type mDummyRegion;
symbol_type *mPrevFunction;
BBEvent mPrevEvent;
symbol_type *mUserFunction;
BBEvent mUserEvent; // the previous user-mode event
uint64_t mSkippedTime;
uint64_t mLastRunTime;
static MethodRec sCurrentMethod;
static MethodRec sNextMethod;
};
template<class FRAME, class BASE>
MethodRec CallStack<FRAME, BASE>::sCurrentMethod;
template<class FRAME, class BASE>
MethodRec CallStack<FRAME, BASE>::sNextMethod;
template<class FRAME, class BASE>
CallStack<FRAME, BASE>::CallStack(int id, int numFrames, TraceReaderType *trace)
{
mNativeOnly = false;
mTrace = trace;
BASE::setId(id);
mNumFrames = numFrames;
mFrames = new FRAME[mNumFrames];
mTop = 0;
mAllowNativeFrames = true;
memset(&mDummyFunction, 0, sizeof(symbol_type));
memset(&mDummyRegion, 0, sizeof(region_type));
mDummyFunction.region = &mDummyRegion;
mPrevFunction = &mDummyFunction;
memset(&mPrevEvent, 0, sizeof(BBEvent));
mUserFunction = &mDummyFunction;
memset(&mUserEvent, 0, sizeof(BBEvent));
mSkippedTime = 0;
mLastRunTime = 0;
// Read the first two methods from the trace if we haven't already read
// from the method trace yet.
if (sCurrentMethod.time == 0) {
if (mTrace->ReadMethod(&sCurrentMethod)) {
sCurrentMethod.time = ~0ull;
sNextMethod.time = ~0ull;
}
if (sNextMethod.time != ~0ull && mTrace->ReadMethod(&sNextMethod)) {
sNextMethod.time = ~0ull;
}
}
}
template<class FRAME, class BASE>
CallStack<FRAME, BASE>::~CallStack()
{
delete mFrames;
}
template<class FRAME, class BASE>
void
CallStack<FRAME, BASE>::updateStack(BBEvent *event, symbol_type *function)
{
if (mNativeOnly) {
// If this is an interpreted function, then use the native VM function
// instead.
if (function->vm_sym != NULL)
function = function->vm_sym;
} else {
doMethodAction(event, function);
}
Action action = getAction(event, function);
// Allow native frames if we are executing in the kernel.
if (!mAllowNativeFrames
&& (function->region->flags & region_type::kIsKernelRegion) == 0) {
action = NONE;
}
if (function->vm_sym != NULL) {
function = function->vm_sym;
function->vm_sym = NULL;
}
if (action == PUSH) {
doPush(event, function);
} else if (action == POP) {
doPop(event, function, NONE);
}
#if 0
// Pop off native functions before pushing or popping Java methods.
if (action == POP && mPrevFunction->vm_sym == NULL) {
// Pop off the previous function first.
doPop(event, function, NONE);
if (methodAction == POP) {
doPop(event, function, POP);
} else if (methodAction == PUSH) {
doPush(event, function);
}
} else {
if (methodAction != NONE) {
// If the method trace has a push or pop, then do it.
action = methodAction;
} else if (function->vm_sym != NULL) {
// This function is a Java method. Don't push or pop the
// Java method without a corresponding method trace record.
action = NONE;
}
if (action == POP) {
doPop(event, function, methodAction);
} else if (action == PUSH) {
doPush(event, function);
}
}
#endif
// If the stack is now empty, then push the current function.
if (mTop == 0) {
uint64_t time = event->time - mSkippedTime;
int flags = 0;
if (function->vm_sym != NULL) {
flags = FRAME::kInterpreted;
}
doSimplePush(function, 0, time, 0);
}
mPrevFunction = function;
mPrevEvent = *event;
}
template<class FRAME, class BASE>
void
CallStack<FRAME, BASE>::threadStart(uint64_t time)
{
mSkippedTime += time - mLastRunTime;
}
template<class FRAME, class BASE>
void
CallStack<FRAME, BASE>::threadStop(uint64_t time)
{
mLastRunTime = time;
}
template<class FRAME, class BASE>
typename CallStack<FRAME, BASE>::Action
CallStack<FRAME, BASE>::getAction(BBEvent *event, symbol_type *function)
{
Action action;
uint32_t offset;
// Compute the offset from the start of the function to this basic
// block address.
offset = event->bb_addr - function->addr - function->region->base_addr;
// Get the previously executed instruction
Opcode op = OP_INVALID;
int numInsns = mPrevEvent.num_insns;
uint32_t insn = 0;
if (numInsns > 0) {
insn = mPrevEvent.insns[numInsns - 1];
if (mPrevEvent.is_thumb) {
insn = insn_unwrap_thumb(insn);
op = decode_insn_thumb(insn);
} else {
op = Arm::decode(insn);
}
}
// The number of bytes in the previous basic block depends on
// whether the basic block was ARM or THUMB instructions.
int numBytes;
if (mPrevEvent.is_thumb) {
numBytes = numInsns << 1;
} else {
numBytes = numInsns << 2;
}
// If this basic block follows the previous one, then return NONE.
// If we don't do this, then we may be fooled into thinking this
// is a POP if the previous block ended with a conditional
// (non-executed) ldmia instruction. We do this check before
// checking if we are in a different function because we otherwise
// we might be fooled into thinking this is a PUSH to a new function
// when it is really just a fall-thru into a local kernel symbol
// that just looks like a new function.
uint32_t prev_end_addr = mPrevEvent.bb_addr + numBytes;
if (prev_end_addr == event->bb_addr) {
return NONE;
}
// If this basic block is in the same function as the last basic block,
// then just return NONE (but see the exceptions below).
// Exception 1: if the function calls itself (offset == 0) then we
// want to push this function.
// Exception 2: if the function returns to itself, then we want
// to pop this function. We detect this case by checking if the last
// instruction in the previous basic block was a load-multiple (ldm)
// and included r15 as one of the loaded registers.
if (function == mPrevFunction) {
if (numInsns > 0) {
// If this is the beginning of the function and the previous
// instruction was not a branch, then it's a PUSH.
if (offset == 0 && op != OP_B && op != OP_THUMB_B)
return PUSH;
// If the previous instruction was an ldm that loaded r15,
// then it's a POP.
if (offset != 0 && ((op == OP_LDM && (insn & 0x8000))
|| (op == OP_THUMB_POP && (insn & 0x100)))) {
return POP;
}
}
return NONE;
}
// We have to figure out if this new function is a call or a
// return. We don't necessarily have a complete call stack (since
// we could have started tracing at any point), so we have to use
// heuristics. If the address we are jumping to is the beginning
// of a function, or if the instruction that took us there was
// either "bl" or "blx" then this is a PUSH. Also, if the
// function offset is non-zero and the previous instruction is a
// branch instruction, we will call it a PUSH. This happens in
// the kernel a lot when there is a branch to an offset from a
// label. A couple more special cases:
//
// - entering a .plt section ("procedure linkage table") is a PUSH,
// - an exception that jumps into the kernel vector entry point
// is also a push.
//
// If the function offset is non-zero and the previous instruction
// is a bx or some non-branch instruction, then it's a POP.
//
// There's another special case that comes up. The user code
// might execute an instruction that returns but before the pc
// starts executing in the caller, a kernel interrupt occurs.
// But it may be hard to tell if this is a return until after
// the kernel interrupt code is done and returns to user space.
// So we save the last user basic block and look at it when
// we come back into user space.
const uint32_t kIsKernelRegion = region_type::kIsKernelRegion;
if (((mPrevFunction->region->flags & kIsKernelRegion) == 0)
&& (function->region->flags & kIsKernelRegion)) {
// We just switched into the kernel. Save the previous
// user-mode basic block and function.
mUserEvent = mPrevEvent;
mUserFunction = mPrevFunction;
} else if ((mPrevFunction->region->flags & kIsKernelRegion)
&& ((function->region->flags & kIsKernelRegion) == 0)) {
// We just switched from kernel to user mode.
return POP;
}
action = PUSH;
if (offset != 0 && mPrevFunction != &mDummyFunction) {
// We are jumping into the middle of a function, so this is
// probably a return, not a function call. But look at the
// previous instruction first to see if it was a branch-and-link.
// If the previous instruction was not a branch (and not a
// branch-and-link) then POP; or if it is a "bx" instruction
// then POP because that is used to return from functions.
if (!isBranch(op) || op == OP_BX || op == OP_THUMB_BX) {
action = POP;
} else if (isBranch(op) && !isBranchLink(op)) {
// If the previous instruction was a normal branch to a
// local symbol then don't count it as a push or a pop.
action = NONE;
}
if (function->flags & symbol_type::kIsVectorTable)
action = PUSH;
}
return action;
}
template<class FRAME, class BASE>
void CallStack<FRAME, BASE>::doPush(BBEvent *event, symbol_type *function)
{
uint64_t time = event->time - mSkippedTime;
// Check for stack overflow
if (mTop >= mNumFrames) {
// Don't show the stack by default because this generates a lot
// of output and this is seen by users if there is an error when
// post-processing the trace. But this is useful for debugging.
#if 0
showStack(stderr);
#endif
fprintf(stderr, "Error: stack overflow (%d frames)\n", mTop);
exit(1);
}
// Compute the return address here because we may need to change
// it if we are popping off a frame for a vector table.
int numBytes;
if (mPrevEvent.is_thumb) {
numBytes = mPrevEvent.num_insns << 1;
} else {
numBytes = mPrevEvent.num_insns << 2;
}
uint32_t retAddr = mPrevEvent.bb_addr + numBytes;
// If this is a Java method then set the return address to zero.
// We won't be using it for popping the method and it may lead
// to false matches when searching the stack.
if (function->vm_sym != NULL) {
retAddr = 0;
}
#if 0
// For debugging only. Show the stack before entering the kernel
// exception-handling code.
if (function->flags & symbol_type::kIsVectorStart) {
printf("stack before entering exception\n");
showStack(stderr);
}
#endif
// If the top of stack is a vector table, then pop it
// off before pushing on the new function. Also, change the
// return address for the new function to the return address
// from the vector table.
if (mTop > 0
&& (mFrames[mTop - 1].function->flags & symbol_type::kIsVectorTable)) {
retAddr = mFrames[mTop - 1].addr;
doSimplePop(time);
}
const uint32_t kIsKernelRegion = region_type::kIsKernelRegion;
// The following code handles the case where one function, F1,
// calls another function, F2, but the before F2 can start
// executing, it takes a page fault (on the first instruction
// in F2). The kernel is entered, handles the page fault, and
// then returns to the called function. The problem is that
// this looks like a new function call to F2 from the kernel.
// The following code cleans up the stack by popping the
// kernel frames back to F1 (but not including F1). The
// return address for F2 also has to be fixed up to point to
// F1 instead of the kernel.
//
// We detect this case by checking if the previous basic block
// was in the kernel and the current basic block is not.
if ((mPrevFunction->region->flags & kIsKernelRegion)
&& ((function->region->flags & kIsKernelRegion) == 0)
&& mTop > 0) {
// We are switching from kernel mode to user mode.
#if 0
// For debugging.
printf(" doPush(): popping to user mode, bb_addr: 0x%08x\n",
event->bb_addr);
showStack(stderr);
#endif
do {
// Pop off the kernel frames until we reach the one that
// caused the exception.
doSimplePop(time);
// If the next stack frame is the one that caused an
// exception then stop popping frames.
if (mTop > 0
&& (mFrames[mTop - 1].flags & FRAME::kCausedException)) {
mFrames[mTop - 1].flags &= ~FRAME::kCausedException;
retAddr = mFrames[mTop].addr;
break;
}
} while (mTop > 0);
#if 0
// For debugging
printf(" doPush() popping to level %d, using retAddr 0x%08x\n",
mTop, retAddr);
#endif
}
// If we are starting an exception handler, then mark the previous
// stack frame so that we know where to return when the exception
// handler finishes.
if ((function->flags & symbol_type::kIsVectorStart) && mTop > 0)
mFrames[mTop - 1].flags |= FRAME::kCausedException;
// If the function being pushed is a Java method, then mark it on
// the stack so that we don't pop it off until we get a matching
// trace record from the method trace file.
int flags = 0;
if (function->vm_sym != NULL) {
flags = FRAME::kInterpreted;
}
doSimplePush(function, retAddr, time, flags);
}
template<class FRAME, class BASE>
void CallStack<FRAME, BASE>::doSimplePush(symbol_type *function, uint32_t addr,
uint64_t time, int flags)
{
// Check for stack overflow
if (mTop >= mNumFrames) {
showStack(stderr);
fprintf(stderr, "too many stack frames (%d)\n", mTop);
exit(1);
}
mFrames[mTop].addr = addr;
mFrames[mTop].function = function;
mFrames[mTop].flags = flags;
mFrames[mTop].time = time;
mFrames[mTop].global_time = time + mSkippedTime;
mFrames[mTop].push(mTop, time, this);
mTop += 1;
}
template<class FRAME, class BASE>
void CallStack<FRAME, BASE>::doSimplePop(uint64_t time)
{
if (mTop <= 0) {
return;
}
mTop -= 1;
mFrames[mTop].pop(mTop, time, this);
if (mNativeOnly)
return;
// If the stack is empty, then allow more native frames.
// Otherwise, if we are transitioning from Java to native, then allow
// more native frames.
// Otherwise, if we are transitioning from native to Java, then disallow
// more native frames.
if (mTop == 0) {
mAllowNativeFrames = true;
} else {
bool newerIsJava = (mFrames[mTop].flags & FRAME::kInterpreted) != 0;
bool olderIsJava = (mFrames[mTop - 1].flags & FRAME::kInterpreted) != 0;
if (newerIsJava && !olderIsJava) {
// We are transitioning from Java to native
mAllowNativeFrames = true;
} else if (!newerIsJava && olderIsJava) {
// We are transitioning from native to Java
mAllowNativeFrames = false;
}
}
}
template<class FRAME, class BASE>
void CallStack<FRAME, BASE>::doPop(BBEvent *event, symbol_type *function,
Action methodAction)
{
uint64_t time = event->time - mSkippedTime;
// Search backward on the stack for a matching return address.
// The most common case is that we pop one stack frame, but
// sometimes we pop more than one.
int stackLevel;
bool allowMethodPop = (methodAction == POP);
for (stackLevel = mTop - 1; stackLevel >= 0; --stackLevel) {
if (event->bb_addr == mFrames[stackLevel].addr) {
// We found a matching return address on the stack.
break;
}
// If this stack frame caused an exception, then do not pop
// this stack frame.
if (mFrames[stackLevel].flags & FRAME::kPopBarrier) {
// If this is a Java method, then allow a pop only if we
// have a matching trace record.
if (mFrames[stackLevel].flags & FRAME::kInterpreted) {
if (allowMethodPop) {
// Allow at most one method pop
allowMethodPop = false;
continue;
}
}
stackLevel += 1;
break;
}
}
// If we didn't find a matching return address then search the stack
// again for a matching function.
if (stackLevel < 0 || event->bb_addr != mFrames[stackLevel].addr) {
bool allowMethodPop = (methodAction == POP);
for (stackLevel = mTop - 1; stackLevel >= 0; --stackLevel) {
// Compare the function with the one in the stack frame.
if (function == mFrames[stackLevel].function) {
// We found a matching function. We want to pop up to but not
// including this frame. But allow popping this frame if this
// method called itself and we have a method pop.
if (allowMethodPop && function == mPrevFunction) {
// pop this frame
break;
}
// do not pop this frame
stackLevel += 1;
break;
}
// If this stack frame caused an exception, then do not pop
// this stack frame.
if (mFrames[stackLevel].flags & FRAME::kPopBarrier) {
// If this is a Java method, then allow a pop only if we
// have a matching trace record.
if (mFrames[stackLevel].flags & FRAME::kInterpreted) {
if (allowMethodPop) {
// Allow at most one method pop
allowMethodPop = false;
continue;
}
}
stackLevel += 1;
break;
}
}
if (stackLevel < 0)
stackLevel = 0;
}
// Note that if we didn't find a matching stack frame, we will pop
// the whole stack (unless there is a Java method or exception
// frame on the stack). This is intentional because we may have
// started the trace in the middle of an executing program that is
// returning up the stack and we do not know the whole stack. So
// the right thing to do is to empty the stack.
// If we are emptying the stack, then add the current function
// on top. If the current function is the same as the top of
// stack, then avoid an extraneous pop and push.
if (stackLevel == 0 && mFrames[0].function == function)
stackLevel = 1;
#if 0
// If we are popping off a large number of stack frames, then
// we might have a bug.
if (mTop - stackLevel > 7) {
printf("popping thru level %d\n", stackLevel);
showStack(stderr);
}
#endif
// Pop the stack frames
for (int ii = mTop - 1; ii >= stackLevel; --ii)
doSimplePop(time);
// Clear the "caused exception" bit on the current stack frame
if (mTop > 0) {
mFrames[mTop - 1].flags &= ~FRAME::kCausedException;
}
// Also handle the case where F1 calls F2 and F2 returns to
// F1, but before we can execute any instructions in F1, we
// switch to the kernel. Then when we return from the kernel
// we want to pop off F2 from the stack instead of pushing F1
// on top of F2. To handle this case, we saved the last
// user-mode basic block when we entered the kernel (in
// the getAction() function) and now we can check to see if
// that was a return to F1 instead of a call. We use the
// getAction() function to determine this.
const uint32_t kIsKernelRegion = region_type::kIsKernelRegion;
if ((mPrevFunction->region->flags & kIsKernelRegion)
&& ((function->region->flags & kIsKernelRegion) == 0)) {
mPrevEvent = mUserEvent;
mPrevFunction = mUserFunction;
if (getAction(event, function) == POP) {
// We may need to pop more than one frame, so just
// call doPop() again. This won't be an infinite loop
// here because we changed mPrevEvent to the last
// user-mode event.
doPop(event, function, methodAction);
return;
}
}
}
template<class FRAME, class BASE>
void CallStack<FRAME, BASE>::popAll(uint64_t time)
{
time -= mSkippedTime;
while (mTop != 0) {
doSimplePop(time);
}
}
template<class FRAME, class BASE>
void CallStack<FRAME, BASE>::doMethodPop(BBEvent *event, uint32_t addr,
const uint32_t flags)
{
uint64_t time = event->time - mSkippedTime;
// Search the stack from the top down for a frame that contains a
// matching method.
int stackLevel;
for (stackLevel = mTop - 1; stackLevel >= 0; --stackLevel) {
if (mFrames[stackLevel].flags & flags) {
// If we are searching for a native method, then don't bother trying
// to match the address.
if (flags == FRAME::kStartNative)
break;
symbol_type *func = mFrames[stackLevel].function;
uint32_t methodAddr = func->region->base_addr + func->addr;
if (methodAddr == addr) {
break;
}
}
}
// If we found a matching frame then pop the stack up to and including
// that frame.
if (stackLevel >= 0) {
// Pop the stack frames
for (int ii = mTop - 1; ii >= stackLevel; --ii)
doSimplePop(time);
}
}
template<class FRAME, class BASE>
void CallStack<FRAME, BASE>::doMethodAction(BBEvent *event, symbol_type *function)
{
// If the events get ahead of the method trace, then read ahead until we
// sync up again. This can happen if there is a pop of a method in the
// method trace for which we don't have a previous push. Such an unmatched
// pop can happen because the user can start tracing at any time and so
// there might already be a stack when we start tracing.
while (event->time >= sNextMethod.time) {
sCurrentMethod = sNextMethod;
if (mTrace->ReadMethod(&sNextMethod)) {
sNextMethod.time = ~0ull;
}
}
if (event->time >= sCurrentMethod.time && event->pid == sCurrentMethod.pid) {
uint64_t time = event->time - mSkippedTime;
int flags = sCurrentMethod.flags;
if (flags == kMethodEnter) {
doSimplePush(function, 0, time, FRAME::kInterpreted);
mAllowNativeFrames = false;
} else if (flags == kNativeEnter) {
doSimplePush(function, 0, time, FRAME::kStartNative);
mAllowNativeFrames = true;
} else if (flags == kMethodExit || flags == kMethodException) {
doMethodPop(event, sCurrentMethod.addr, FRAME::kInterpreted);
} else if (flags == kNativeExit || flags == kNativeException) {
doMethodPop(event, sCurrentMethod.addr, FRAME::kStartNative);
}
// We found a match, so read the next record. When we get to the end
// of the trace, we set the time to the maximum value (~0).
sCurrentMethod = sNextMethod;
if (sNextMethod.time != ~0ull && mTrace->ReadMethod(&sNextMethod)) {
sNextMethod.time = ~0ull;
}
}
}
template<class FRAME, class BASE>
void CallStack<FRAME, BASE>::showStack(FILE *stream)
{
fprintf(stream, "mTop: %d skippedTime: %llu\n", mTop, mSkippedTime);
for (int ii = 0; ii < mTop; ++ii) {
uint32_t addr = mFrames[ii].function->addr;
addr += mFrames[ii].function->region->vstart;
fprintf(stream, " %d: t %d gt %d f %x 0x%08x 0x%08x %s\n",
ii, mFrames[ii].time, mFrames[ii].global_time,
mFrames[ii].flags,
mFrames[ii].addr, addr,
mFrames[ii].function->name);
}
}
#endif /* CALL_STACK_H */

View File

@@ -1,270 +0,0 @@
// Copyright 2009 The Android Open Source Project
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
#include <assert.h>
#include "trace_reader.h"
#include "bitvector.h"
#include "parse_options.h"
#include "armdis.h"
typedef TraceReader<> TraceReaderType;
#include "parse_options-inl.h"
#include "callstack.h"
typedef CallStack<StackFrame<symbol_type> > CallStackType;
void compareStacks(uint64_t time, int pid);
void dumpStacks(int pid);
static uint64_t debugTime;
static const int kNumStackFrames = 500;
static const int kMaxThreads = (32 * 1024);
CallStackType *eStacks[kMaxThreads];
int numErrors;
static const int kMaxErrors = 3;
struct frame {
uint64_t time;
uint32_t addr;
const char *name;
bool isNative;
frame(uint64_t time, uint32_t addr, const char *name, bool isNative) {
this->time = time;
this->addr = addr;
this->name = name;
this->isNative = isNative;
}
};
class Stack {
public:
static const int kMaxFrames = 1000;
int top;
frame *frames[kMaxFrames];
Stack() {
top = 0;
}
void push(frame *pframe);
frame* pop();
void dump();
};
void Stack::push(frame *pframe) {
if (top == kMaxFrames) {
fprintf(stderr, "Error: stack overflow\n");
exit(1);
}
frames[top] = pframe;
top += 1;
}
frame *Stack::pop() {
if (top <= 0)
return NULL;
top -= 1;
return frames[top];
}
Stack *mStacks[kMaxThreads];
void Usage(const char *program)
{
fprintf(stderr, "Usage: %s [options] trace_name elf_file\n",
program);
OptionsUsage();
}
int main(int argc, char **argv)
{
ParseOptions(argc, argv);
if (argc - optind != 2) {
Usage(argv[0]);
exit(1);
}
char *qemu_trace_file = argv[optind++];
char *elf_file = argv[optind++];
TraceReaderType *etrace = new TraceReaderType;
etrace->Open(qemu_trace_file);
etrace->ReadKernelSymbols(elf_file);
etrace->SetRoot(root);
TraceReaderType *mtrace = new TraceReaderType;
mtrace->Open(qemu_trace_file);
mtrace->ReadKernelSymbols(elf_file);
mtrace->SetRoot(root);
BBEvent event;
while (1) {
BBEvent ignored;
symbol_type *function;
MethodRec method_record;
symbol_type *sym;
TraceReaderType::ProcessState *proc;
frame *pframe;
if (mtrace->ReadMethodSymbol(&method_record, &sym, &proc))
break;
if (!IsValidPid(proc->pid))
continue;
// Get the stack for the current thread
Stack *mStack = mStacks[proc->pid];
// If the stack does not exist, then allocate a new one.
if (mStack == NULL) {
mStack = new Stack();
mStacks[proc->pid] = mStack;
}
int flags = method_record.flags;
if (flags == kMethodEnter || flags == kNativeEnter) {
pframe = new frame(method_record.time, method_record.addr,
sym == NULL ? NULL: sym->name,
method_record.flags == kNativeEnter);
mStack->push(pframe);
} else {
pframe = mStack->pop();
delete pframe;
}
do {
if (GetNextValidEvent(etrace, &event, &ignored, &function))
break;
if (event.bb_num == 0)
break;
// Get the stack for the current thread
CallStackType *eStack = eStacks[event.pid];
// If the stack does not exist, then allocate a new one.
if (eStack == NULL) {
eStack = new CallStackType(event.pid, kNumStackFrames, etrace);
eStacks[event.pid] = eStack;
}
if (debugTime != 0 && event.time >= debugTime)
printf("time: %llu debug time: %lld\n", event.time, debugTime);
// Update the stack
eStack->updateStack(&event, function);
} while (event.time < method_record.time);
compareStacks(event.time, event.pid);
}
for (int ii = 0; ii < kMaxThreads; ++ii) {
if (eStacks[ii])
eStacks[ii]->popAll(event.time);
}
delete etrace;
delete mtrace;
return 0;
}
void compareStacks(uint64_t time, int pid) {
CallStackType *eStack = eStacks[pid];
Stack *mStack = mStacks[pid];
frame **mFrames = mStack->frames;
frame *mframe;
int mTop = mStack->top;
int eTop = eStack->mTop;
CallStackType::frame_type *eFrames = eStack->mFrames;
// Count the number of non-native methods (ie, Java methods) on the
// Java method stack
int numNonNativeMethods = 0;
for (int ii = 0; ii < mTop; ++ii) {
if (!mFrames[ii]->isNative) {
numNonNativeMethods += 1;
}
}
// Count the number of Java methods on the native stack
int numMethods = 0;
for (int ii = 0; ii < eTop; ++ii) {
if (eFrames[ii].flags & CallStackType::frame_type::kInterpreted) {
numMethods += 1;
}
}
// Verify that the number of Java methods on both stacks are the same.
// Allow the native stack to have one less Java method because the
// native stack might be pushing a native function first.
if (numNonNativeMethods != numMethods && numNonNativeMethods != numMethods + 1) {
printf("\nDiff at time %llu pid %d: non-native %d numMethods %d\n",
time, pid, numNonNativeMethods, numMethods);
dumpStacks(pid);
numErrors += 1;
if (numErrors >= kMaxErrors)
exit(1);
}
// Verify that the Java methods on the method stack are the same
// as the Java methods on the native stack.
int mIndex = 0;
for (int ii = 0; ii < eTop; ++ii) {
// Ignore native functions on the native stack.
if ((eFrames[ii].flags & CallStackType::frame_type::kInterpreted) == 0)
continue;
uint32_t addr = eFrames[ii].function->addr;
addr += eFrames[ii].function->region->vstart;
while (mIndex < mTop && mFrames[mIndex]->isNative) {
mIndex += 1;
}
if (mIndex >= mTop)
break;
if (addr != mFrames[mIndex]->addr) {
printf("\nDiff at time %llu pid %d: frame %d\n", time, pid, ii);
dumpStacks(pid);
exit(1);
}
mIndex += 1;
}
}
void dumpStacks(int pid) {
CallStackType *eStack = eStacks[pid];
Stack *mStack = mStacks[pid];
frame *mframe;
int mTop = mStack->top;
printf("\nJava method stack\n");
for (int ii = 0; ii < mTop; ii++) {
mframe = mStack->frames[ii];
const char *native = mframe->isNative ? "n" : " ";
printf(" %s %d: %llu 0x%x %s\n",
native, ii, mframe->time, mframe->addr,
mframe->name == NULL ? "" : mframe->name);
}
int eTop = eStack->mTop;
CallStackType::frame_type *eFrames = eStack->mFrames;
int mIndex = 0;
printf("\nNative stack\n");
for (int ii = 0; ii < eTop; ++ii) {
uint32_t addr = eFrames[ii].function->addr;
addr += eFrames[ii].function->region->vstart;
const char *marker = " ";
if (eFrames[ii].flags & CallStackType::frame_type::kInterpreted) {
if (mIndex >= mTop || addr != mStack->frames[mIndex]->addr) {
marker = "*";
}
mIndex += 1;
}
printf(" %s %d: %d f %d 0x%08x %s\n",
marker, ii, eFrames[ii].time, eFrames[ii].flags, addr,
eFrames[ii].function->name);
}
}

View File

@@ -1,61 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
#include <assert.h>
#include "trace_reader.h"
#include "armdis.h"
#include "parse_options.h"
typedef TraceReader<> TraceReaderType;
#include "parse_options-inl.h"
static const uint32_t kOffsetThreshold = 0x100000;
void Usage(const char *program)
{
fprintf(stderr, "Usage: %s [options] trace_file elf_file\n", program);
OptionsUsage();
}
int main(int argc, char **argv) {
// Parse the options
ParseOptions(argc, argv);
if (argc - optind != 2) {
Usage(argv[0]);
exit(1);
}
char *trace_filename = argv[optind++];
char *elf_file = argv[optind++];
TraceReader<> *trace = new TraceReader<>;
trace->Open(trace_filename);
trace->ReadKernelSymbols(elf_file);
trace->SetRoot(root);
while (1) {
symbol_type *sym;
BBEvent event;
BBEvent ignored;
if (GetNextValidEvent(trace, &event, &ignored, &sym))
break;
if (event.bb_num == 0)
break;
//printf("t%llu bb %lld %d\n", event.time, event.bb_num, event.num_insns);
uint64_t insn_time = trace->ReadInsnTime(event.time);
if (insn_time != event.time) {
printf("time: %llu insn time: %llu bb: %llu addr: 0x%x num_insns: %d, pid: %d\n",
event.time, insn_time, event.bb_num, event.bb_addr,
event.num_insns, event.pid);
exit(1);
}
for (int ii = 1; ii < event.num_insns; ++ii) {
trace->ReadInsnTime(event.time);
}
}
delete trace;
return 0;
}

View File

@@ -1,153 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "trace_reader.h"
#include "parse_options.h"
#include "opcode.h"
const int kMillion = 1000000;
const int kMHz = 200 * kMillion;
struct symbol {
int numCalls; // number of times this function is called
};
typedef TraceReader<symbol> TraceReaderType;
#include "parse_options-inl.h"
#include "callstack.h"
class MyFrame : public StackFrame<symbol_type> {
public:
void push(int stackLevel, uint64_t time, CallStackBase *base) {
function->numCalls += 1;
}
void pop(int stackLevel, uint64_t time, CallStackBase *base) {
}
};
typedef CallStack<MyFrame> CallStackType;
static const int kNumStackFrames = 500;
static const int kMaxThreads = (32 * 1024);
CallStackType *stacks[kMaxThreads];
// This comparison function is called from qsort() to sort symbols
// into decreasing number of calls.
int cmp_sym_calls(const void *a, const void *b) {
const symbol_type *syma, *symb;
uint64_t calls1, calls2;
syma = static_cast<symbol_type const *>(a);
symb = static_cast<symbol_type const *>(b);
calls1 = syma->numCalls;
calls2 = symb->numCalls;
if (calls1 < calls2)
return 1;
if (calls1 == calls2) {
int cmp = strcmp(syma->name, symb->name);
if (cmp == 0)
cmp = strcmp(syma->region->path, symb->region->path);
return cmp;
}
return -1;
}
// This comparison function is called from qsort() to sort symbols
// into alphabetical order.
int cmp_sym_names(const void *a, const void *b) {
const symbol_type *syma, *symb;
syma = static_cast<symbol_type const *>(a);
symb = static_cast<symbol_type const *>(b);
int cmp = strcmp(syma->region->path, symb->region->path);
if (cmp == 0)
cmp = strcmp(syma->name, symb->name);
return cmp;
}
void Usage(const char *program)
{
fprintf(stderr, "Usage: %s [options] trace_file elf_file\n", program);
OptionsUsage();
}
int main(int argc, char **argv)
{
ParseOptions(argc, argv);
if (argc - optind != 2) {
Usage(argv[0]);
exit(1);
}
char *trace_filename = argv[optind++];
char *elf_file = argv[optind++];
TraceReader<symbol> *trace = new TraceReader<symbol>;
trace->Open(trace_filename);
trace->SetDemangle(demangle);
trace->ReadKernelSymbols(elf_file);
trace->SetRoot(root);
BBEvent event;
while (1) {
BBEvent ignored;
symbol_type *function;
if (GetNextValidEvent(trace, &event, &ignored, &function))
break;
if (event.bb_num == 0)
break;
// Get the stack for the current thread
CallStackType *pStack = stacks[event.pid];
// If the stack does not exist, then allocate a new one.
if (pStack == NULL) {
pStack = new CallStackType(event.pid, kNumStackFrames, trace);
stacks[event.pid] = pStack;
}
// Update the stack
pStack->updateStack(&event, function);
}
for (int ii = 0; ii < kMaxThreads; ++ii) {
if (stacks[ii])
stacks[ii]->popAll(event.time);
}
int nsyms;
symbol_type *syms = trace->GetSymbols(&nsyms);
// Sort the symbols into decreasing number of calls
qsort(syms, nsyms, sizeof(symbol_type), cmp_sym_names);
symbol_type *psym = syms;
for (int ii = 0; ii < nsyms; ++ii, ++psym) {
// Ignore functions with non-zero calls
if (psym->numCalls)
continue;
// Ignore some symbols
if (strcmp(psym->name, "(end)") == 0)
continue;
if (strcmp(psym->name, "(unknown)") == 0)
continue;
if (strcmp(psym->name, ".plt") == 0)
continue;
const char *ksym = " ";
if (psym->region->flags & region_type::kIsKernelRegion)
ksym = "k";
printf("%s %s %s\n", ksym, psym->name, psym->region->path);
#if 0
printf("#%d %5d %s %s %s\n", ii + 1, psym->numCalls, ksym, psym->name,
psym->region->path);
#endif
}
delete[] syms;
delete trace;
return 0;
}

View File

@@ -1,278 +0,0 @@
// Copyright 2006 The Android Open Source Project
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "decoder.h"
#include "trace_common.h"
// This array provides a fast conversion from the initial byte in
// a varint-encoded object to the length (in bytes) of that object.
int prefix_to_len[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 9, 9, 17, 17
};
// This array provides a fast conversion from the initial byte in
// a varint-encoded object to the initial data bits for that object.
int prefix_to_data[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 0, 0, 0, 0
};
signed char prefix_to_signed_data[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0x00, 0x01, 0x02, 0x03, 0xfc, 0xfd, 0xfe, 0xff,
0x00, 0x01, 0xfe, 0xff, 0x00, 0xff, 0x00, 0xff,
};
Decoder::Decoder()
{
filename_ = NULL;
fstream_ = NULL;
next_ = NULL;
end_ = NULL;
}
Decoder::~Decoder()
{
Close();
delete[] filename_;
}
void Decoder::Close()
{
if (fstream_) {
fclose(fstream_);
fstream_ = NULL;
}
}
void Decoder::Open(char *filename)
{
if (filename_ != NULL) {
delete[] filename_;
}
filename_ = new char[strlen(filename) + 1];
strcpy(filename_, filename);
fstream_ = fopen(filename_, "r");
if (fstream_ == NULL) {
perror(filename_);
exit(1);
}
int rval = fread(buf_, 1, kBufSize, fstream_);
if (rval != kBufSize) {
if (ferror(fstream_)) {
perror(filename_);
exit(1);
}
if (!feof(fstream_)) {
fprintf(stderr, "Unexpected short fread() before eof\n");
exit(1);
}
}
next_ = buf_;
end_ = buf_ + rval;
}
void Decoder::FillBuffer()
{
assert(next_ <= end_);
if (end_ - next_ < kDecodingSpace && end_ == &buf_[kBufSize]) {
// Copy the unused bytes left at the end to the beginning of the
// buffer.
int len = end_ - next_;
if (len > 0)
memcpy(buf_, next_, len);
// Read enough bytes to fill up the buffer, if possible.
int nbytes = kBufSize - len;
int rval = fread(buf_ + len, 1, nbytes, fstream_);
if (rval < nbytes) {
if (ferror(fstream_)) {
perror(filename_);
exit(1);
}
if (!feof(fstream_)) {
fprintf(stderr, "Unexpected short fread() before eof\n");
exit(1);
}
}
end_ = &buf_[len + rval];
next_ = buf_;
}
}
void Decoder::Read(char *dest, int len)
{
while (len > 0) {
int nbytes = end_ - next_;
if (nbytes == 0) {
FillBuffer();
nbytes = end_ - next_;
if (nbytes == 0)
break;
}
if (nbytes > len)
nbytes = len;
memcpy(dest, next_, nbytes);
dest += nbytes;
len -= nbytes;
next_ += nbytes;
}
}
// Decode a varint-encoded object starting at the current position in
// the array "buf_" and return the decoded value as a 64-bit integer.
// A varint-encoded object has an initial prefix that specifies how many
// data bits follow. If the first bit is zero, for example, then there
// are 7 data bits that follow. The table below shows the prefix values
// and corresponding data bits.
//
// Prefix Bytes Data bits
// 0 1 7
// 10 2 14
// 110 3 21
// 1110 4 28
// 11110 5 35
// 111110 6 42
// 11111100 9 64
// 11111101 reserved
// 11111110 reserved
// 11111111 reserved
int64_t Decoder::Decode(bool is_signed)
{
int64_t val64;
if (end_ - next_ < kDecodingSpace)
FillBuffer();
#if BYTE_ORDER == BIG_ENDIAN
uint8_t byte0 = *next_;
// Get the number of bytes to decode based on the first byte.
int len = prefix_to_len[byte0];
if (next_ + len > end_) {
fprintf(stderr, "%s: decoding past end of file.\n", filename_);
exit(1);
}
// Get the first data byte.
if (is_signed)
val64 = prefix_to_signed_data[byte0];
else
val64 = prefix_to_data[byte0];
next_ += 1;
for (int ii = 1; ii < len; ++ii) {
val64 = (val64 << 8) | *next_++;
}
#else
// If we are on a little-endian machine, then use large, unaligned loads.
uint64_t data = *(reinterpret_cast<uint64_t*>(next_));
uint8_t byte0 = data;
data = bswap64(data);
// Get the number of bytes to decode based on the first byte.
int len = prefix_to_len[byte0];
if (next_ + len > end_) {
fprintf(stderr, "%s: decoding past end of file.\n", filename_);
exit(1);
}
// Get the first data byte.
if (is_signed)
val64 = prefix_to_signed_data[byte0];
else
val64 = prefix_to_data[byte0];
switch (len) {
case 1:
break;
case 2:
val64 = (val64 << 8) | ((data >> 48) & 0xffull);
break;
case 3:
val64 = (val64 << 16) | ((data >> 40) & 0xffffull);
break;
case 4:
val64 = (val64 << 24) | ((data >> 32) & 0xffffffull);
break;
case 5:
val64 = (val64 << 32) | ((data >> 24) & 0xffffffffull);
break;
case 6:
val64 = (val64 << 40) | ((data >> 16) & 0xffffffffffull);
break;
case 9:
data = *(reinterpret_cast<uint64_t*>(&next_[1]));
val64 = bswap64(data);
break;
}
next_ += len;
#endif
return val64;
}

View File

@@ -1,28 +0,0 @@
// Copyright 2006 The Android Open Source Project
#include <stdio.h>
#include <inttypes.h>
class Decoder {
public:
Decoder();
~Decoder();
void Open(char *filename);
void Close();
int64_t Decode(bool is_signed);
void Read(char *dest, int len);
bool IsEOF() { return (end_ == next_) && feof(fstream_); }
private:
static const int kBufSize = 4096;
static const int kDecodingSpace = 9;
void FillBuffer();
char *filename_;
FILE *fstream_;
uint8_t buf_[kBufSize];
uint8_t *next_;
uint8_t *end_;
};

View File

@@ -1,255 +0,0 @@
// Copyright 2006 The Android Open Source Project
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
#include "dmtrace.h"
static const short kVersion = 2;
const DmTrace::Header DmTrace::header = {
0x574f4c53, kVersion, sizeof(DmTrace::Header), 0LL
};
static char *keyHeader = "*version\n" "2\n" "clock=thread-cpu\n";
static char *keyThreadHeader = "*threads\n";
static char *keyFunctionHeader = "*methods\n";
static char *keyEnd = "*end\n";
DmTrace::DmTrace() {
fData = NULL;
fTrace = NULL;
threads = new std::vector<ThreadRecord*>;
functions = new std::vector<FunctionRecord*>;
}
DmTrace::~DmTrace() {
delete threads;
delete functions;
}
void DmTrace::open(const char *dmtrace_file, uint64_t start_time)
{
fTrace = fopen(dmtrace_file, "w");
if (fTrace == NULL) {
perror(dmtrace_file);
exit(1);
}
// Make a temporary file to write the data into.
char tmpData[32];
strcpy(tmpData, "/tmp/dmtrace-data-XXXXXX");
int data_fd = mkstemp(tmpData);
if (data_fd < 0) {
perror("Cannot create temporary file");
exit(1);
}
// Ensure it goes away on exit.
unlink(tmpData);
fData = fdopen(data_fd, "w+");
if (fData == NULL) {
perror("Can't make temp data file");
exit(1);
}
writeHeader(fData, start_time);
}
void DmTrace::close()
{
if (fTrace == NULL)
return;
writeKeyFile(fTrace);
// Take down how much data we wrote to the temp data file.
long size = ftell(fData);
// Rewind the data file and append its contents to the trace file.
rewind(fData);
char *data = (char *)malloc(size);
fread(data, size, 1, fData);
fwrite(data, size, 1, fTrace);
free(data);
fclose(fData);
fclose(fTrace);
}
/*
* Write values to the binary data file.
*/
void DmTrace::write2LE(FILE* fstream, unsigned short val)
{
putc(val & 0xff, fstream);
putc(val >> 8, fstream);
}
void DmTrace::write4LE(FILE* fstream, unsigned int val)
{
putc(val & 0xff, fstream);
putc((val >> 8) & 0xff, fstream);
putc((val >> 16) & 0xff, fstream);
putc((val >> 24) & 0xff, fstream);
}
void DmTrace::write8LE(FILE* fstream, unsigned long long val)
{
putc(val & 0xff, fstream);
putc((val >> 8) & 0xff, fstream);
putc((val >> 16) & 0xff, fstream);
putc((val >> 24) & 0xff, fstream);
putc((val >> 32) & 0xff, fstream);
putc((val >> 40) & 0xff, fstream);
putc((val >> 48) & 0xff, fstream);
putc((val >> 56) & 0xff, fstream);
}
void DmTrace::writeHeader(FILE *fstream, uint64_t startTime)
{
write4LE(fstream, header.magic);
write2LE(fstream, header.version);
write2LE(fstream, header.offset);
write8LE(fstream, startTime);
}
void DmTrace::writeDataRecord(FILE *fstream, int threadId,
unsigned int methodVal,
unsigned int elapsedTime)
{
write2LE(fstream, threadId);
write4LE(fstream, methodVal);
write4LE(fstream, elapsedTime);
}
void DmTrace::addFunctionEntry(int functionId, uint32_t cycle, uint32_t pid)
{
writeDataRecord(fData, pid, functionId, cycle);
}
void DmTrace::addFunctionExit(int functionId, uint32_t cycle, uint32_t pid)
{
writeDataRecord(fData, pid, functionId | 1, cycle);
}
void DmTrace::addFunction(int functionId, const char *name)
{
FunctionRecord *rec = new FunctionRecord;
rec->id = functionId;
rec->name = name;
functions->push_back(rec);
}
void DmTrace::addFunction(int functionId, const char *clazz,
const char *method, const char *sig)
{
// Allocate space for all the strings, plus 2 tab separators plus null byte.
// We currently don't reclaim this space.
int len = strlen(clazz) + strlen(method) + strlen(sig) + 3;
char *name = new char[len];
sprintf(name, "%s\t%s\t%s", clazz, method, sig);
addFunction(functionId, name);
}
void DmTrace::parseAndAddFunction(int functionId, const char *name)
{
// Parse the "name" string into "class", "method" and "signature".
// The "name" string should look something like this:
// name = "java.util.LinkedList.size()I"
// and it will be parsed into this:
// clazz = "java.util.LinkedList"
// method = "size"
// sig = "()I"
// Find the first parenthesis, the start of the signature.
char *paren = (char*)strchr(name, '(');
// If not found, then add the original name.
if (paren == NULL) {
addFunction(functionId, name);
return;
}
// Copy the signature
int len = strlen(paren) + 1;
char *sig = new char[len];
strcpy(sig, paren);
// Zero the parenthesis so that we can search backwards from the signature
*paren = 0;
// Search for the last period, the start of the method name
char *dot = (char*)strrchr(name, '.');
// If not found, then add the original name.
if (dot == NULL || dot == name) {
delete[] sig;
*paren = '(';
addFunction(functionId, name);
return;
}
// Copy the method, not including the dot
len = strlen(dot + 1) + 1;
char *method = new char[len];
strcpy(method, dot + 1);
// Zero the dot to delimit the class name
*dot = 0;
addFunction(functionId, name, method, sig);
// Free the space we allocated.
delete[] sig;
delete[] method;
}
void DmTrace::addThread(int threadId, const char *name)
{
ThreadRecord *rec = new ThreadRecord;
rec->id = threadId;
rec->name = name;
threads->push_back(rec);
}
void DmTrace::updateName(int threadId, const char *name)
{
std::vector<ThreadRecord*>::iterator iter;
for (iter = threads->begin(); iter != threads->end(); ++iter) {
if ((*iter)->id == threadId) {
(*iter)->name = name;
return;
}
}
}
void DmTrace::writeKeyFile(FILE *fstream)
{
fwrite(keyHeader, strlen(keyHeader), 1, fstream);
writeThreads(fstream);
writeFunctions(fstream);
fwrite(keyEnd, strlen(keyEnd), 1, fstream);
}
void DmTrace::writeThreads(FILE *fstream)
{
std::vector<ThreadRecord*>::iterator iter;
fwrite(keyThreadHeader, strlen(keyThreadHeader), 1, fstream);
for (iter = threads->begin(); iter != threads->end(); ++iter) {
fprintf(fstream, "%d\t%s\n", (*iter)->id, (*iter)->name);
}
}
void DmTrace::writeFunctions(FILE *fstream)
{
std::vector<FunctionRecord*>::iterator iter;
fwrite(keyFunctionHeader, strlen(keyFunctionHeader), 1, fstream);
for (iter = functions->begin(); iter != functions->end(); ++iter) {
fprintf(fstream, "0x%x\t%s\n", (*iter)->id, (*iter)->name);
}
}

View File

@@ -1,61 +0,0 @@
// Copyright 2006 The Android Open Source Project
#ifndef DMTRACE_H
#define DMTRACE_H
#include <vector>
class DmTrace {
public:
struct Header {
uint32_t magic;
uint16_t version;
uint16_t offset;
uint64_t date_time;
};
DmTrace();
~DmTrace();
void open(const char *dmtrace_file, uint64_t startTime);
void close();
void addFunctionEntry(int methodId, uint32_t cycle, uint32_t pid);
void addFunctionExit(int methodId, uint32_t cycle, uint32_t pid);
void addFunction(int functionId, const char *name);
void addFunction(int functionId, const char *clazz, const char *method,
const char *sig);
void parseAndAddFunction(int functionId, const char *name);
void addThread(int threadId, const char *name);
void updateName(int threadId, const char *name);
private:
static const Header header;
struct ThreadRecord {
int id;
const char *name;
};
struct FunctionRecord {
int id;
const char *name;
};
void write2LE(FILE* fstream, unsigned short val);
void write4LE(FILE* fstream, unsigned int val);
void write8LE(FILE* fstream, unsigned long long val);
void writeHeader(FILE *fstream, uint64_t startTime);
void writeDataRecord(FILE *fstream, int threadId,
unsigned int methodVal,
unsigned int elapsedTime);
void writeKeyFile(FILE *fstream);
void writeThreads(FILE *fstream);
void writeFunctions(FILE *fstream);
FILE *fData;
FILE *fTrace;
std::vector<ThreadRecord*> *threads;
std::vector<FunctionRecord*> *functions;
};
#endif // DMTRACE_H

View File

@@ -1,59 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include "trace_reader.h"
#include "parse_options.h"
typedef TraceReader<> TraceReaderType;
#include "parse_options-inl.h"
void Usage(const char *program)
{
fprintf(stderr, "Usage: %s [options] trace_file\n", program);
OptionsUsage();
}
int main(int argc, char **argv) {
// Parse the options
ParseOptions(argc, argv);
if (argc - optind != 1) {
Usage(argv[0]);
exit(1);
}
char *trace_filename = argv[optind];
TraceReader<> *trace = new TraceReader<>;
trace->Open(trace_filename);
trace->SetRoot(root);
while (1) {
BBEvent event, ignored;
symbol_type *dummy_sym;
if (GetNextValidEvent(trace, &event, &ignored, &dummy_sym))
break;
}
int num_procs;
ProcessState *processes = trace->GetProcesses(&num_procs);
ProcessState *pstate = &processes[0];
for (int ii = 0; ii < num_procs; ++ii, ++pstate) {
if (pstate->name == NULL)
pstate->name = "";
ProcessState *manager = pstate->addr_manager;
printf("pid %d regions: %d %s",
pstate->pid, manager->nregions, pstate->name);
for (int jj = 1; jj < pstate->argc; ++jj) {
printf(" %s", pstate->argv[jj]);
}
printf("\n");
trace->DumpRegions(stdout, pstate);
}
delete trace;
return 0;
}

View File

@@ -1,28 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "trace_reader_base.h"
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s trace_file\n", argv[0]);
exit(1);
}
char *trace_filename = argv[1];
TraceReaderBase *trace = new TraceReaderBase;
trace->Open(trace_filename);
while (1) {
uint64_t time, recnum, bb_num, bb_start_time;
uint32_t pc, target_pc;
int num_insns;
if (trace->ReadExc(&time, &pc, &recnum, &target_pc, &bb_num,
&bb_start_time, &num_insns))
break;
printf("time: %lld rec: %llu pc: %08x target: %08x bb: %llu bb_start: %llu insns: %d\n",
time, recnum, pc, target_pc, bb_num, bb_start_time, num_insns);
}
return 0;
}

View File

@@ -1,152 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "gtrace.h"
// A buffer of zeros
static char zeros[Gtrace::kGtraceEntriesPerBlock * sizeof(Gtrace::trace_entry)];
Gtrace::Gtrace() {
gtrace_file_ = NULL;
ftrace_ = NULL;
fnames_ = NULL;
start_sec_ = 0;
pdate_ = 0;
ptime_ = 0;
num_entries_ = 0;
blockno_ = 1;
current_pid_ = 0;
}
Gtrace::~Gtrace() {
if (ftrace_) {
// Extend the trace file to a multiple of 8k. Otherwise gtracepost64
// complains.
long pos = ftell(ftrace_);
long pos_end = (pos + 0x1fff) & ~0x1fff;
if (pos_end > pos) {
char ch = 0;
fseek(ftrace_, pos_end - 1, SEEK_SET);
fwrite(&ch, 1, 1, ftrace_);
}
fclose(ftrace_);
}
if (fnames_)
fclose(fnames_);
}
void Gtrace::Open(const char *gtrace_file, uint32_t pdate, uint32_t ptime)
{
ftrace_ = fopen(gtrace_file, "w");
if (ftrace_ == NULL) {
perror(gtrace_file);
exit(1);
}
gtrace_file_ = gtrace_file;
pdate_ = pdate;
ptime_ = ptime;
sprintf(gname_file_, "gname_%x_%06x.txt", pdate, ptime);
fnames_ = fopen(gname_file_, "w");
if (fnames_ == NULL) {
perror(gname_file_);
exit(1);
}
fprintf(fnames_, "# File# Proc# Line# Name\n");
}
void Gtrace::WriteFirstHeader(uint32_t start_sec, uint32_t pid)
{
first_header fh;
current_pid_ = pid;
start_sec_ = start_sec;
FillFirstHeader(start_sec, pid, &fh);
fwrite(&fh, sizeof(fh), 1, ftrace_);
num_entries_ = 8;
}
void Gtrace::FillFirstHeader(uint32_t start_sec, uint32_t pid,
first_header *fh) {
int cpu = 0;
int max_files = 16;
int max_procedures = 12;
fh->common.blockno = 0;
fh->common.entry_width = 8;
fh->common.block_tic = kBaseTic;
fh->common.block_time = start_sec;
//fh->common.usec_cpu = (start_usec << 8) | (cpu & 0xff);
fh->common.usec_cpu = cpu & 0xff;
fh->common.pid = pid;
fh->common.bug_count = 0;
fh->common.zero_count = 0;
fh->tic = kBaseTic + 1;
fh->one = 1;
fh->tics_per_second = kTicsPerSecond;
fh->trace_time = start_sec;
fh->version = 5;
fh->file_proc = (max_files << 8) | max_procedures;
fh->pdate = pdate_;
fh->ptime = ptime_;
}
void Gtrace::WriteBlockHeader(uint32_t cycle, uint32_t pid)
{
int cpu = 0;
block_header bh;
bh.blockno = blockno_++;
bh.entry_width = 8;
bh.block_tic = cycle + kBaseTic;
bh.block_time = start_sec_ + cycle / kTicsPerSecond;
//bh.usec_cpu = (start_usec << 8) | (cpu & 0xff);
bh.usec_cpu = cpu & 0xff;
bh.pid = pid;
bh.bug_count = 0;
bh.zero_count = 0;
fwrite(&bh, sizeof(bh), 1, ftrace_);
}
void Gtrace::AddGtraceRecord(int filenum, int procnum, uint32_t cycle, uint32_t pid,
int is_exit)
{
trace_entry entry;
if (current_pid_ != pid) {
current_pid_ = pid;
// We are switching to a new process id, so pad the current block
// with zeros.
int num_zeros = (kGtraceEntriesPerBlock - num_entries_) * sizeof(entry);
fwrite(zeros, num_zeros, 1, ftrace_);
WriteBlockHeader(cycle, pid);
num_entries_ = 4;
}
// If the current block is full, write out a new block header
if (num_entries_ == kGtraceEntriesPerBlock) {
WriteBlockHeader(cycle, pid);
num_entries_ = 4;
}
entry.cycle = cycle + kBaseTic;
entry.event = (filenum << 13) | (procnum << 1) | is_exit;
fwrite(&entry, sizeof(entry), 1, ftrace_);
num_entries_ += 1;
}
void Gtrace::AddProcEntry(int filenum, int procnum, uint32_t cycle, uint32_t pid)
{
AddGtraceRecord(filenum, procnum, cycle, pid, 0);
}
void Gtrace::AddProcExit(int filenum, int procnum, uint32_t cycle, uint32_t pid)
{
AddGtraceRecord(filenum, procnum, cycle, pid, 1);
}
void Gtrace::AddProcedure(int filenum, int procnum, const char *proc_name)
{
fprintf(fnames_, "%d %d %d %s\n", filenum, procnum, procnum, proc_name);
}

View File

@@ -1,69 +0,0 @@
// Copyright 2006 The Android Open Source Project
#ifndef GTRACE_H
#define GTRACE_H
class Gtrace {
public:
static const int kGtraceEntriesPerBlock = 1024;
static const uint32_t kMillion = 1000000;
static const uint32_t kTicsPerSecond = 200 * kMillion;
static const int kBaseTic = 0x1000;
struct trace_entry {
uint32_t cycle;
uint32_t event;
};
struct block_header {
uint32_t blockno;
uint32_t entry_width;
uint32_t block_tic;
uint32_t block_time;
uint32_t usec_cpu;
uint32_t pid;
uint32_t bug_count;
uint32_t zero_count;
};
struct first_header {
block_header common;
uint32_t tic;
uint32_t one;
uint32_t tics_per_second;
uint32_t trace_time;
uint32_t version;
uint32_t file_proc;
uint32_t pdate;
uint32_t ptime;
};
Gtrace();
~Gtrace();
void Open(const char *gtrace_file, uint32_t pdate, uint32_t ptime);
void WriteFirstHeader(uint32_t start_sec, uint32_t pid);
void AddProcedure(int filenum, int procnum, const char *proc_name);
void AddProcEntry(int filenum, int procnum, uint32_t cycle, uint32_t pid);
void AddProcExit(int filenum, int procnum, uint32_t cycle, uint32_t pid);
private:
void AddGtraceRecord(int filenum, int procnum, uint32_t cycle, uint32_t pid,
int is_exit);
void FillFirstHeader(uint32_t start_sec, uint32_t pid,
first_header *fh);
void WriteBlockHeader(uint32_t cycle, uint32_t pid);
const char *gtrace_file_;
char gname_file_[100];
FILE *ftrace_;
FILE *fnames_;
uint32_t start_sec_;
uint32_t pdate_;
uint32_t ptime_;
int num_entries_;
int blockno_;
uint32_t current_pid_;
};
#endif // GTRACE_H

View File

@@ -1,219 +0,0 @@
// Copyright 2006 The Android Open Source Project
#ifndef HASH_TABLE_H
#define HASH_TABLE_H
#include <string.h>
#include <inttypes.h>
template<class T>
class HashTable {
public:
HashTable(int size, T default_value = T());
~HashTable();
typedef struct entry {
entry *next;
char *key;
T value;
} entry_type;
typedef T value_type;
void Update(const char *key, T value);
bool Remove(const char *key);
T Find(const char *key);
entry_type* GetFirst();
entry_type* GetNext();
private:
uint32_t HashFunction(const char *key);
int size_;
int mask_;
T default_value_;
entry_type **table_;
int num_entries_;
int current_index_;
entry_type *current_ptr_;
};
template<class T>
HashTable<T>::HashTable(int size, T default_value)
{
int pow2;
// Round up size to a power of two
for (pow2 = 2; pow2 < size; pow2 <<= 1)
; // empty body
size_ = pow2;
mask_ = pow2 - 1;
default_value_ = default_value;
// Allocate a table of pointers and initialize them all to NULL.
table_ = new entry_type*[size_];
for (int ii = 0; ii < size_; ++ii)
table_[ii] = NULL;
num_entries_ = 0;
current_index_ = 0;
current_ptr_ = NULL;
}
template<class T>
HashTable<T>::~HashTable()
{
for (int ii = 0; ii < size_; ++ii) {
entry_type *ptr, *next;
// Delete all the pointers in the chain at this table position.
// Save the next pointer before deleting each entry so that we
// don't dereference part of a deallocated object.
for (ptr = table_[ii]; ptr; ptr = next) {
next = ptr->next;
delete[] ptr->key;
delete ptr;
}
}
delete[] table_;
}
// Professor Daniel J. Bernstein's hash function. See
// http://www.partow.net/programming/hashfunctions/
template<class T>
uint32_t HashTable<T>::HashFunction(const char *key)
{
uint32_t hash = 5381;
int len = strlen(key);
for(int ii = 0; ii < len; ++key, ++ii)
hash = ((hash << 5) + hash) + *key;
return hash;
}
template<class T>
void HashTable<T>::Update(const char *key, T value)
{
// Hash the key to get the table position
int len = strlen(key);
int pos = HashFunction(key) & mask_;
// Search the chain for a matching key
for (entry_type *ptr = table_[pos]; ptr; ptr = ptr->next) {
if (strcmp(ptr->key, key) == 0) {
ptr->value = value;
return;
}
}
// Create a new hash entry and fill in the values
entry_type *ptr = new entry_type;
// Copy the string
ptr->key = new char[len + 1];
strcpy(ptr->key, key);
ptr->value = value;
// Insert the new entry at the beginning of the list
ptr->next = table_[pos];
table_[pos] = ptr;
num_entries_ += 1;
}
template<class T>
bool HashTable<T>::Remove(const char *key)
{
// Hash the key to get the table position
int len = strlen(key);
int pos = HashFunction(key) & mask_;
// Search the chain for a matching key and keep track of the previous
// element in the chain.
entry_type *prev = NULL;
for (entry_type *ptr = table_[pos]; ptr; prev = ptr, ptr = ptr->next) {
if (strcmp(ptr->key, key) == 0) {
if (prev == NULL) {
table_[pos] = ptr->next;
} else {
prev->next = ptr->next;
}
delete ptr->key;
delete ptr;
return true;
}
}
return false;
}
template<class T>
typename HashTable<T>::value_type HashTable<T>::Find(const char *key)
{
// Hash the key to get the table position
int pos = HashFunction(key) & mask_;
// Search the chain for a matching key
for (entry_type *ptr = table_[pos]; ptr; ptr = ptr->next) {
if (strcmp(ptr->key, key) == 0)
return ptr->value;
}
// If we get here, then we didn't find the key
return default_value_;
}
template<class T>
typename HashTable<T>::entry_type* HashTable<T>::GetFirst()
{
// Find the first non-NULL table entry.
for (current_index_ = 0; current_index_ < size_; ++current_index_) {
if (table_[current_index_])
break;
}
// If there are no table entries, then return NULL.
if (current_index_ == size_)
return NULL;
// Remember and return the current element.
current_ptr_ = table_[current_index_];
return current_ptr_;
}
template<class T>
typename HashTable<T>::entry_type* HashTable<T>::GetNext()
{
// If we already iterated part way through the hash table, then continue
// to the next element.
if (current_ptr_) {
current_ptr_ = current_ptr_->next;
// If we are pointing to a valid element, then return it.
if (current_ptr_)
return current_ptr_;
// Otherwise, start searching at the next table index.
current_index_ += 1;
}
// Find the next non-NULL table entry.
for (; current_index_ < size_; ++current_index_) {
if (table_[current_index_])
break;
}
// If there are no more non-NULL table entries, then return NULL.
if (current_index_ == size_) {
// Reset the current index so that we will start over from the
// beginning on the next call to GetNext().
current_index_ = 0;
return NULL;
}
// Remember and return the current element.
current_ptr_ = table_[current_index_];
return current_ptr_;
}
#endif // HASH_TABLE_H

View File

@@ -1,64 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "trace_reader.h"
static const int kMaxHistEntries = 256;
static const int kMaxHistEntries2 = kMaxHistEntries / 2;
int hist[kMaxHistEntries];
int underflow, overflow;
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s trace_file\n", argv[0]);
exit(1);
}
char *trace_filename = argv[1];
TraceReaderBase *trace = new TraceReaderBase;
trace->Open(trace_filename);
uint64_t prev_bb_num = 0;
uint64_t prev_time = 0;
int total = 0;
while (1) {
BBEvent event;
if (trace->ReadBB(&event))
break;
int bb_diff = event.bb_num - prev_bb_num;
//int time_diff = event.time - prev_time;
//printf("bb_num: %llu prev: %llu, diff: %d\n",
// event.bb_num, prev_bb_num, bb_diff);
prev_bb_num = event.bb_num;
prev_time = event.time;
bb_diff += kMaxHistEntries2;
if (bb_diff < 0)
underflow += 1;
else if (bb_diff >= kMaxHistEntries)
overflow += 1;
else
hist[bb_diff] += 1;
total += 1;
}
int sum = 0;
double sum_per = 0;
double per = 0;
for (int ii = 0; ii < kMaxHistEntries; ++ii) {
if (hist[ii] == 0)
continue;
per = 100.0 * hist[ii] / total;
sum += hist[ii];
sum_per = 100.0 * sum / total;
printf(" %4d: %6d %6.2f %6.2f\n", ii - kMaxHistEntries2, hist[ii], per, sum_per);
}
per = 100.0 * underflow / total;
printf("under: %6d %6.2f\n", underflow, per);
per = 100.0 * overflow / total;
printf("over: %6d %6.2f\n", overflow, per);
printf("total: %6d\n", total);
return 0;
}

View File

@@ -1,204 +0,0 @@
// Copyright 2006 The Android Open Source Project
#include <stdio.h>
#include <inttypes.h>
#include "opcode.h"
// Note: this array depends on the Opcode enum defined in opcode.h
uint32_t opcode_flags[] = {
0, // OP_INVALID
0, // OP_UNDEFINED
kCatAlu, // OP_ADC
kCatAlu, // OP_ADD
kCatAlu, // OP_AND
kCatBranch, // OP_B
kCatBranch | kCatBranchLink, // OP_BL
kCatAlu, // OP_BIC
0, // OP_BKPT
kCatBranch | kCatBranchLink | kCatBranchExch, // OP_BLX
kCatBranch | kCatBranchExch, // OP_BX
kCatCoproc, // OP_CDP
kCatAlu, // OP_CLZ
kCatAlu, // OP_CMN
kCatAlu, // OP_CMP
kCatAlu, // OP_EOR
kCatCoproc | kCatLoad, // OP_LDC
kCatLoad | kCatMultiple, // OP_LDM
kCatLoad | kCatWord, // OP_LDR
kCatLoad | kCatByte, // OP_LDRB
kCatLoad | kCatByte, // OP_LDRBT
kCatLoad | kCatHalf, // OP_LDRH
kCatLoad | kCatByte | kCatSigned, // OP_LDRSB
kCatLoad | kCatHalf | kCatSigned, // OP_LDRSH
kCatLoad | kCatWord, // OP_LDRT
kCatCoproc, // OP_MCR
kCatAlu, // OP_MLA
kCatAlu, // OP_MOV
kCatCoproc, // OP_MRC
0, // OP_MRS
0, // OP_MSR
kCatAlu, // OP_MUL
kCatAlu, // OP_MVN
kCatAlu, // OP_ORR
0, // OP_PLD
kCatAlu, // OP_RSB
kCatAlu, // OP_RSC
kCatAlu, // OP_SBC
kCatAlu, // OP_SMLAL
kCatAlu, // OP_SMULL
kCatCoproc | kCatStore, // OP_STC
kCatStore | kCatMultiple, // OP_STM
kCatStore | kCatWord, // OP_STR
kCatStore | kCatByte, // OP_STRB
kCatStore | kCatByte, // OP_STRBT
kCatStore | kCatHalf, // OP_STRH
kCatStore | kCatWord, // OP_STRT
kCatAlu, // OP_SUB
0, // OP_SWI
kCatLoad | kCatStore, // OP_SWP
kCatLoad | kCatStore | kCatByte, // OP_SWPB
kCatAlu, // OP_TEQ
kCatAlu, // OP_TST
kCatAlu, // OP_UMLAL
kCatAlu, // OP_UMULL
0, // OP_THUMB_UNDEFINED,
kCatAlu, // OP_THUMB_ADC,
kCatAlu, // OP_THUMB_ADD,
kCatAlu, // OP_THUMB_AND,
kCatAlu, // OP_THUMB_ASR,
kCatBranch, // OP_THUMB_B,
kCatAlu, // OP_THUMB_BIC,
0, // OP_THUMB_BKPT,
kCatBranch | kCatBranchLink, // OP_THUMB_BL,
kCatBranch | kCatBranchLink | kCatBranchExch, // OP_THUMB_BLX,
kCatBranch | kCatBranchExch, // OP_THUMB_BX,
kCatAlu, // OP_THUMB_CMN,
kCatAlu, // OP_THUMB_CMP,
kCatAlu, // OP_THUMB_EOR,
kCatLoad | kCatMultiple, // OP_THUMB_LDMIA,
kCatLoad | kCatWord, // OP_THUMB_LDR,
kCatLoad | kCatByte, // OP_THUMB_LDRB,
kCatLoad | kCatHalf, // OP_THUMB_LDRH,
kCatLoad | kCatByte | kCatSigned, // OP_THUMB_LDRSB,
kCatLoad | kCatHalf | kCatSigned, // OP_THUMB_LDRSH,
kCatAlu, // OP_THUMB_LSL,
kCatAlu, // OP_THUMB_LSR,
kCatAlu, // OP_THUMB_MOV,
kCatAlu, // OP_THUMB_MUL,
kCatAlu, // OP_THUMB_MVN,
kCatAlu, // OP_THUMB_NEG,
kCatAlu, // OP_THUMB_ORR,
kCatLoad | kCatMultiple, // OP_THUMB_POP,
kCatStore | kCatMultiple, // OP_THUMB_PUSH,
kCatAlu, // OP_THUMB_ROR,
kCatAlu, // OP_THUMB_SBC,
kCatStore | kCatMultiple, // OP_THUMB_STMIA,
kCatStore | kCatWord, // OP_THUMB_STR,
kCatStore | kCatByte, // OP_THUMB_STRB,
kCatStore | kCatHalf, // OP_THUMB_STRH,
kCatAlu, // OP_THUMB_SUB,
0, // OP_THUMB_SWI,
kCatAlu, // OP_THUMB_TST,
0, // OP_END
};
const char *opcode_names[] = {
"invalid",
"undefined",
"adc",
"add",
"and",
"b",
"bl",
"bic",
"bkpt",
"blx",
"bx",
"cdp",
"clz",
"cmn",
"cmp",
"eor",
"ldc",
"ldm",
"ldr",
"ldrb",
"ldrbt",
"ldrh",
"ldrsb",
"ldrsh",
"ldrt",
"mcr",
"mla",
"mov",
"mrc",
"mrs",
"msr",
"mul",
"mvn",
"orr",
"pld",
"rsb",
"rsc",
"sbc",
"smlal",
"smull",
"stc",
"stm",
"str",
"strb",
"strbt",
"strh",
"strt",
"sub",
"swi",
"swp",
"swpb",
"teq",
"tst",
"umlal",
"umull",
"undefined",
"adc",
"add",
"and",
"asr",
"b",
"bic",
"bkpt",
"bl",
"blx",
"bx",
"cmn",
"cmp",
"eor",
"ldmia",
"ldr",
"ldrb",
"ldrh",
"ldrsb",
"ldrsh",
"lsl",
"lsr",
"mov",
"mul",
"mvn",
"neg",
"orr",
"pop",
"push",
"ror",
"sbc",
"stmia",
"str",
"strb",
"strh",
"sub",
"swi",
"tst",
NULL
};

View File

@@ -1,166 +0,0 @@
// Copyright 2006 The Android Open Source Project
#ifndef OPCODE_H
#define OPCODE_H
#include <inttypes.h>
// Note: this list of opcodes must match the list used to initialize
// the opflags[] array in opcode.cpp.
enum Opcode {
OP_INVALID,
OP_UNDEFINED,
OP_ADC,
OP_ADD,
OP_AND,
OP_B,
OP_BL,
OP_BIC,
OP_BKPT,
OP_BLX,
OP_BX,
OP_CDP,
OP_CLZ,
OP_CMN,
OP_CMP,
OP_EOR,
OP_LDC,
OP_LDM,
OP_LDR,
OP_LDRB,
OP_LDRBT,
OP_LDRH,
OP_LDRSB,
OP_LDRSH,
OP_LDRT,
OP_MCR,
OP_MLA,
OP_MOV,
OP_MRC,
OP_MRS,
OP_MSR,
OP_MUL,
OP_MVN,
OP_ORR,
OP_PLD,
OP_RSB,
OP_RSC,
OP_SBC,
OP_SMLAL,
OP_SMULL,
OP_STC,
OP_STM,
OP_STR,
OP_STRB,
OP_STRBT,
OP_STRH,
OP_STRT,
OP_SUB,
OP_SWI,
OP_SWP,
OP_SWPB,
OP_TEQ,
OP_TST,
OP_UMLAL,
OP_UMULL,
// Define thumb opcodes
OP_THUMB_UNDEFINED,
OP_THUMB_ADC,
OP_THUMB_ADD,
OP_THUMB_AND,
OP_THUMB_ASR,
OP_THUMB_B,
OP_THUMB_BIC,
OP_THUMB_BKPT,
OP_THUMB_BL,
OP_THUMB_BLX,
OP_THUMB_BX,
OP_THUMB_CMN,
OP_THUMB_CMP,
OP_THUMB_EOR,
OP_THUMB_LDMIA,
OP_THUMB_LDR,
OP_THUMB_LDRB,
OP_THUMB_LDRH,
OP_THUMB_LDRSB,
OP_THUMB_LDRSH,
OP_THUMB_LSL,
OP_THUMB_LSR,
OP_THUMB_MOV,
OP_THUMB_MUL,
OP_THUMB_MVN,
OP_THUMB_NEG,
OP_THUMB_ORR,
OP_THUMB_POP,
OP_THUMB_PUSH,
OP_THUMB_ROR,
OP_THUMB_SBC,
OP_THUMB_STMIA,
OP_THUMB_STR,
OP_THUMB_STRB,
OP_THUMB_STRH,
OP_THUMB_SUB,
OP_THUMB_SWI,
OP_THUMB_TST,
OP_END // must be last
};
extern uint32_t opcode_flags[];
extern const char *opcode_names[];
// Define bit flags for the opcode categories
static const uint32_t kCatByte = 0x0001;
static const uint32_t kCatHalf = 0x0002;
static const uint32_t kCatWord = 0x0004;
static const uint32_t kCatLong = 0x0008;
static const uint32_t kCatNumBytes = (kCatByte | kCatHalf | kCatWord | kCatLong);
static const uint32_t kCatMultiple = 0x0010;
static const uint32_t kCatSigned = 0x0020;
static const uint32_t kCatLoad = 0x0040;
static const uint32_t kCatStore = 0x0080;
static const uint32_t kCatMemoryRef = (kCatLoad | kCatStore);
static const uint32_t kCatAlu = 0x0100;
static const uint32_t kCatBranch = 0x0200;
static const uint32_t kCatBranchLink = 0x0400;
static const uint32_t kCatBranchExch = 0x0800;
static const uint32_t kCatCoproc = 0x1000;
static const uint32_t kCatLoadMultiple = (kCatLoad | kCatMultiple);
static const uint32_t kCatStoreMultiple = (kCatStore | kCatMultiple);
inline bool isALU(Opcode op) { return (opcode_flags[op] & kCatAlu) != 0; }
inline bool isBranch(Opcode op) { return (opcode_flags[op] & kCatBranch) != 0; }
inline bool isBranchLink(Opcode op) {
return (opcode_flags[op] & kCatBranchLink) != 0;
}
inline bool isBranchExch(Opcode op) {
return (opcode_flags[op] & kCatBranchExch) != 0;
}
inline bool isLoad(Opcode op) { return (opcode_flags[op] & kCatLoad) != 0; }
inline bool isLoadMultiple(Opcode op) {
return (opcode_flags[op] & kCatLoadMultiple) == kCatLoadMultiple;
}
inline bool isStoreMultiple(Opcode op) {
return (opcode_flags[op] & kCatStoreMultiple) == kCatStoreMultiple;
}
inline bool isStore(Opcode op) { return (opcode_flags[op] & kCatStore) != 0; }
inline bool isSigned(Opcode op) { return (opcode_flags[op] & kCatSigned) != 0; }
inline bool isMemoryRef(Opcode op) {
return (opcode_flags[op] & kCatMemoryRef) != 0;
}
inline int getAccessSize(Opcode op) { return opcode_flags[op] & kCatNumBytes; }
inline bool isCoproc(Opcode op) { return (opcode_flags[op] & kCatCoproc) != 0; }
inline int getNumAccesses(Opcode op, uint32_t binary) {
extern int num_one_bits[];
int num_accesses = 0;
if (opcode_flags[op] & kCatNumBytes)
num_accesses = 1;
else if (opcode_flags[op] & kCatMultiple) {
num_accesses = num_one_bits[(binary >> 8) & 0xff]
+ num_one_bits[binary & 0xff];
}
return num_accesses;
}
#endif // OPCODE_H

View File

@@ -1,155 +0,0 @@
// Copyright 2006 The Android Open Source Project
#ifndef PARSE_OPTIONS_INL_H
#define PARSE_OPTIONS_INL_H
// Define a typedef for TraceReaderType and include "parse_options.h"
// before including this header file in a C++ source file.
//
// For example:
//
// struct symbol {
// int elapsed;
// };
//
// typedef TraceReader<symbol> TraceReaderType;
typedef TraceReaderType::symbol_type symbol_type;
typedef TraceReaderType::region_type region_type;
typedef TraceReaderType::ProcessState ProcessState;
symbol_type *kernel_sym;
symbol_type *library_sym;
// Returns true if the given event is included (or not excluded)
// from the list of valid events specified by the user on the
// command line.
inline bool IsValidEvent(BBEvent *event, symbol_type *sym)
{
if (include_some_pids && pid_include_vector.GetBit(event->pid) == 0)
return false;
if (exclude_some_pids && pid_exclude_vector.GetBit(event->pid))
return false;
if (include_some_procedures) {
if (sym == NULL || included_procedures.Find(sym->name) == 0)
return false;
}
if (exclude_some_procedures) {
if (sym == NULL || excluded_procedures.Find(sym->name))
return false;
}
return true;
}
inline bool IsValidPid(int pid) {
if (include_some_pids && pid_include_vector.GetBit(pid) == 0)
return false;
if (exclude_some_pids && pid_exclude_vector.GetBit(pid))
return false;
return true;
}
inline symbol_type *GetSymbol(TraceReaderType *trace, int pid, uint32_t addr,
uint64_t time)
{
symbol_type *sym = trace->LookupFunction(pid, addr, time);
if (lump_kernel && (sym->region->flags & region_type::kIsKernelRegion)) {
if (kernel_sym == NULL) {
kernel_sym = sym;
sym->name = ":kernel";
} else {
sym = kernel_sym;
}
}
if (lump_libraries && (sym->region->flags & region_type::kIsLibraryRegion)) {
if (library_sym == NULL) {
library_sym = sym;
sym->name = ":libs";
} else {
sym = library_sym;
}
}
return sym;
}
inline bool IsIncludedProcedure(symbol_type *sym)
{
if (include_kernel_syms && (sym->region->flags & region_type::kIsKernelRegion))
return true;
if (include_library_syms && (sym->region->flags & region_type::kIsLibraryRegion))
return true;
return included_procedures.Find(sym->name);
}
inline bool IsExcludedProcedure(symbol_type *sym)
{
if (exclude_kernel_syms && (sym->region->flags & region_type::kIsKernelRegion))
return true;
if (exclude_library_syms && (sym->region->flags & region_type::kIsLibraryRegion))
return true;
return excluded_procedures.Find(sym->name);
}
// Returns true on end-of-file.
inline bool GetNextValidEvent(TraceReaderType *trace,
BBEvent *event,
BBEvent *first_ignored_event,
symbol_type **sym_ptr)
{
symbol_type *sym = NULL;
first_ignored_event->time = 0;
if (trace->ReadBB(event))
return true;
bool recheck = true;
while (recheck) {
recheck = false;
if (include_some_pids) {
while (pid_include_vector.GetBit(event->pid) == 0) {
if (first_ignored_event->time == 0)
*first_ignored_event = *event;
if (trace->ReadBB(event))
return true;
}
} else if (exclude_some_pids) {
while (pid_exclude_vector.GetBit(event->pid)) {
if (first_ignored_event->time == 0)
*first_ignored_event = *event;
if (trace->ReadBB(event))
return true;
}
}
if (include_some_procedures) {
sym = GetSymbol(trace, event->pid, event->bb_addr, event->time);
while (!IsIncludedProcedure(sym)) {
if (first_ignored_event->time == 0)
*first_ignored_event = *event;
if (trace->ReadBB(event))
return true;
recheck = true;
sym = GetSymbol(trace, event->pid, event->bb_addr, event->time);
}
} else if (exclude_some_procedures) {
sym = GetSymbol(trace, event->pid, event->bb_addr, event->time);
while (IsExcludedProcedure(sym)) {
if (first_ignored_event->time == 0)
*first_ignored_event = *event;
if (trace->ReadBB(event))
return true;
recheck = true;
sym = GetSymbol(trace, event->pid, event->bb_addr, event->time);
}
}
}
if (sym == NULL)
sym = GetSymbol(trace, event->pid, event->bb_addr, event->time);
*sym_ptr = sym;
return false;
}
#endif // PARSE_OPTIONS_INL_H

View File

@@ -1,119 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "bitvector.h"
#include "parse_options.h"
#include "hash_table.h"
const char *root = "";
bool lump_kernel;
bool lump_libraries;
Bitvector pid_include_vector(32768);
Bitvector pid_exclude_vector(32768);
bool include_some_pids;
bool exclude_some_pids;
HashTable<int> excluded_procedures(2000);
HashTable<int> included_procedures(2000);
bool exclude_some_procedures;
bool include_some_procedures;
bool exclude_kernel_syms;
bool exclude_library_syms;
bool include_kernel_syms;
bool include_library_syms;
bool demangle = true;
static const char *OptionsUsageStr =
" -e :kernel exclude all kernel symbols\n"
" -e :libs exclude all library symbols\n"
" -e <func> exclude function <func>\n"
" -e <pid> exclude process <pid>\n"
" -i :kernel include all kernel symbols\n"
" -i :libs include all library symbols\n"
" -i <func> include function <func>\n"
" -i <pid> include process <pid>\n"
" -l :kernel lump all the kernel symbols together\n"
" -l :libs lump all the library symbols together\n"
" -m do not demangle C++ symbols (m for 'mangle')\n"
" -r <root> use <root> as the path for finding ELF executables\n"
;
void OptionsUsage()
{
fprintf(stderr, "%s", OptionsUsageStr);
}
void ParseOptions(int argc, char **argv)
{
bool err = false;
while (!err) {
int opt = getopt(argc, argv, "+e:i:l:mr:");
if (opt == -1)
break;
switch (opt) {
case 'e':
if (*optarg == ':') {
if (strcmp(optarg, ":kernel") == 0)
exclude_kernel_syms = true;
else if (strcmp(optarg, ":libs") == 0)
exclude_library_syms = true;
else
err = true;
excluded_procedures.Update(optarg, 1);
exclude_some_procedures = true;
} else if (isdigit(*optarg)) {
int bitnum = atoi(optarg);
pid_exclude_vector.SetBit(bitnum);
exclude_some_pids = true;
} else {
excluded_procedures.Update(optarg, 1);
exclude_some_procedures = true;
}
break;
case 'i':
if (*optarg == ':') {
if (strcmp(optarg, ":kernel") == 0)
include_kernel_syms = true;
else if (strcmp(optarg, ":libs") == 0)
include_library_syms = true;
else
err = true;
included_procedures.Update(optarg, 1);
include_some_procedures = true;
} else if (isdigit(*optarg)) {
int bitnum = atoi(optarg);
pid_include_vector.SetBit(bitnum);
include_some_pids = true;
} else {
included_procedures.Update(optarg, 1);
include_some_procedures = true;
}
break;
case 'l':
if (strcmp(optarg, ":kernel") == 0)
lump_kernel = true;
else if (strcmp(optarg, ":libs") == 0)
lump_libraries = true;
else
err = true;
break;
case 'm':
demangle = false;
break;
case 'r':
root = optarg;
break;
default:
err = true;
break;
}
}
if (err) {
Usage(argv[0]);
exit(1);
}
}

View File

@@ -1,32 +0,0 @@
// Copyright 2006 The Android Open Source Project
#ifndef PARSE_OPTIONS_H
#define PARSE_OPTIONS_H
#include "bitvector.h"
#include "hash_table.h"
extern const char *root;
extern bool lump_kernel;
extern bool lump_libraries;
extern Bitvector pid_include_vector;
extern Bitvector pid_exclude_vector;
extern bool include_some_pids;
extern bool exclude_some_pids;
extern HashTable<int> excluded_procedures;
extern HashTable<int> included_procedures;
extern bool exclude_some_procedures;
extern bool include_some_procedures;
extern bool exclude_kernel_syms;
extern bool exclude_library_syms;
extern bool include_kernel_syms;
extern bool include_library_syms;
extern bool demangle;
extern void Usage(const char *program);
extern void ParseOptions(int argc, char **argv);
extern void OptionsUsage();
#endif // PARSE_OPTIONS_H

View File

@@ -1,151 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "trace_reader.h"
typedef struct MyStaticRec {
StaticRec bb;
uint32_t *insns;
} MyStaticRec;
const int kNumPids = 32768;
char usedPids[kNumPids];
int main(int argc, char **argv) {
uint32_t insns[kMaxInsnPerBB];
if (argc != 2) {
fprintf(stderr, "Usage: %s trace_file\n", argv[0]);
exit(1);
}
char *trace_filename = argv[1];
TraceReaderBase *trace = new TraceReaderBase;
trace->SetPostProcessing(true);
trace->Open(trace_filename);
// Count the number of static basic blocks and instructions.
uint64_t num_static_bb = 0;
uint64_t num_static_insn = 0;
while (1) {
StaticRec static_rec;
if (trace->ReadStatic(&static_rec))
break;
if (static_rec.bb_num != num_static_bb) {
fprintf(stderr,
"Error: basic block numbers out of order; expected %lld, got %lld\n",
num_static_bb, static_rec.bb_num);
exit(1);
}
num_static_bb += 1;
num_static_insn += static_rec.num_insns;
trace->ReadStaticInsns(static_rec.num_insns, insns);
}
trace->Close();
// Allocate space for all of the static blocks
MyStaticRec *blocks = new MyStaticRec[num_static_bb];
// Read the static blocks again and save pointers to them
trace->Open(trace_filename);
for (uint32_t ii = 0; ii < num_static_bb; ++ii) {
trace->ReadStatic(&blocks[ii].bb);
uint32_t num_insns = blocks[ii].bb.num_insns;
if (num_insns > 0) {
blocks[ii].insns = new uint32_t[num_insns];
trace->ReadStaticInsns(num_insns, blocks[ii].insns);
}
}
// Check the last basic block. If it contains a special undefined
// instruction, then truncate the basic block at that point.
uint32_t num_insns = blocks[num_static_bb - 1].bb.num_insns;
uint32_t *insn_ptr = blocks[num_static_bb - 1].insns;
for (uint32_t ii = 0; ii < num_insns; ++ii, ++insn_ptr) {
if (*insn_ptr == 0xe6c00110) {
uint32_t actual_num_insns = ii + 1;
blocks[num_static_bb - 1].bb.num_insns = actual_num_insns;
num_static_insn -= (num_insns - actual_num_insns);
// Write the changes back to the trace file
trace->TruncateLastBlock(actual_num_insns);
break;
}
}
TraceHeader *header = trace->GetHeader();
strcpy(header->ident, TRACE_IDENT);
header->num_static_bb = num_static_bb;
header->num_dynamic_bb = 0;
header->num_static_insn = num_static_insn;
header->num_dynamic_insn = 0;
trace->WriteHeader(header);
// Reopen the trace file in order to force the trace manager to reread
// the static blocks now that we have written that information to the
// header.
trace->Close();
trace->Open(trace_filename);
// Count the number of dynamic executions of basic blocks and instructions.
// Also keep track of which process ids are used.
uint64_t num_dynamic_bb = 0;
uint64_t num_dynamic_insn = 0;
while (1) {
BBEvent event;
if (trace->ReadBB(&event))
break;
if (event.bb_num >= num_static_bb) {
fprintf(stderr,
"Error: basic block number (%lld) too large (num blocks: %lld)\n",
event.bb_num, num_static_bb);
exit(1);
}
usedPids[event.pid] = 1;
num_dynamic_bb += 1;
num_dynamic_insn += event.num_insns;
}
// Count the number of process ids that are used and remember the first
// unused pid.
int numUsedPids = 0;
int unusedPid = -1;
for (int pid = 0; pid < kNumPids; pid++) {
if (usedPids[pid] == 1) {
numUsedPids += 1;
} else if (unusedPid == -1) {
unusedPid = pid;
}
}
// Rewrite the header with the dynamic counts
header->num_dynamic_bb = num_dynamic_bb;
header->num_dynamic_insn = num_dynamic_insn;
header->num_used_pids = numUsedPids;
header->first_unused_pid = unusedPid;
trace->WriteHeader(header);
trace->Close();
printf("Static basic blocks: %llu, Dynamic basic blocks: %llu\n",
num_static_bb, num_dynamic_bb);
printf("Static instructions: %llu, Dynamic instructions: %llu\n",
num_static_insn, num_dynamic_insn);
double elapsed_secs = header->elapsed_usecs / 1000000.0;
double insn_per_sec = 0;
if (elapsed_secs != 0)
insn_per_sec = num_dynamic_insn / elapsed_secs;
const char *suffix = "";
if (insn_per_sec >= 1000000) {
insn_per_sec /= 1000000.0;
suffix = "M";
} else if (insn_per_sec > 1000) {
insn_per_sec /= 1000.0;
suffix = "K";
}
printf("Elapsed seconds: %.2f, simulated instructions/sec: %.1f%s\n",
elapsed_secs, insn_per_sec, suffix);
return 0;
}

View File

@@ -1,94 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include "trace_reader.h"
#include "parse_options.h"
typedef TraceReader<> TraceReaderType;
#include "parse_options-inl.h"
// This function is called from quicksort to compare the cpu time
// of processes and sort into decreasing order.
int cmp_dec_cpu_time(const void *a, const void *b) {
ProcessState *proc1, *proc2;
proc1 = (ProcessState*)a;
proc2 = (ProcessState*)b;
if (proc1 == NULL) {
if (proc2 == NULL)
return 0;
return 1;
}
if (proc2 == NULL)
return -1;
if (proc1->cpu_time < proc2->cpu_time)
return 1;
if (proc1->cpu_time > proc2->cpu_time)
return -1;
// If the cpu_time times are the same, then sort into increasing
// order of pid.
return proc1->pid - proc2->pid;
}
void Usage(const char *program)
{
fprintf(stderr, "Usage: %s [options] trace_file\n", program);
OptionsUsage();
}
int main(int argc, char **argv) {
// Parse the options
ParseOptions(argc, argv);
if (argc - optind != 1) {
Usage(argv[0]);
exit(1);
}
char *trace_filename = argv[optind];
TraceReader<> *trace = new TraceReader<>;
trace->Open(trace_filename);
trace->SetRoot(root);
while (1) {
BBEvent event, ignored;
symbol_type *dummy_sym;
if (GetNextValidEvent(trace, &event, &ignored, &dummy_sym))
break;
}
int num_procs;
ProcessState *processes = trace->GetProcesses(&num_procs);
qsort(processes, num_procs, sizeof(ProcessState), cmp_dec_cpu_time);
uint64_t total_time = 0;
for (int ii = 0; ii < num_procs; ++ii) {
total_time += processes[ii].cpu_time;
}
uint64_t sum_time = 0;
printf(" pid parent cpu_time %% %% flags argv\n");
ProcessState *pstate = &processes[0];
for (int ii = 0; ii < num_procs; ++ii, ++pstate) {
sum_time += pstate->cpu_time;
double per = 100.0 * pstate->cpu_time / total_time;
double sum_per = 100.0 * sum_time / total_time;
const char *print_flags = "";
if ((pstate->flags & ProcessState::kCalledExec) == 0)
print_flags = "T";
if (pstate->name == NULL)
pstate->name = "";
printf("%5d %5d %10llu %6.2f %6.2f %5s %s",
pstate->pid, pstate->parent_pid, pstate->cpu_time,
per, sum_per, print_flags, pstate->name);
for (int jj = 1; jj < pstate->argc; ++jj) {
printf(" %s", pstate->argv[jj]);
}
printf("\n");
}
delete trace;
return 0;
}

View File

@@ -1,131 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "trace_reader.h"
#include "parse_options.h"
const int kMillion = 1000000;
const int kMHz = 200 * kMillion;
struct symbol {
int count; // number of times a function is executed
uint64_t elapsed; // elapsed time for this function
};
typedef TraceReader<symbol> TraceReaderType;
#include "parse_options-inl.h"
static const uint32_t kOffsetThreshold = 0x100000;
// This comparison function is called from qsort() to sort
// symbols into decreasing elapsed time.
int cmp_sym_elapsed(const void *a, const void *b) {
const symbol_type *syma, *symb;
uint64_t elapsed1, elapsed2;
syma = static_cast<symbol_type const *>(a);
symb = static_cast<symbol_type const *>(b);
elapsed1 = syma->elapsed;
elapsed2 = symb->elapsed;
if (elapsed1 < elapsed2)
return 1;
if (elapsed1 == elapsed2)
return strcmp(syma->name, symb->name);
return -1;
}
void Usage(const char *program)
{
fprintf(stderr, "Usage: %s [options] trace_file elf_file\n", program);
OptionsUsage();
}
int main(int argc, char **argv)
{
ParseOptions(argc, argv);
if (argc - optind != 2) {
Usage(argv[0]);
exit(1);
}
char *trace_filename = argv[optind++];
char *elf_file = argv[optind++];
TraceReader<symbol> *trace = new TraceReader<symbol>;
trace->Open(trace_filename);
trace->SetDemangle(demangle);
trace->ReadKernelSymbols(elf_file);
trace->SetRoot(root);
symbol_type dummy;
dummy.count = 0;
dummy.elapsed = 0;
symbol_type *prev_sym = &dummy;
uint64_t prev_bb_time = 0;
while (1) {
symbol_type *sym;
BBEvent event;
BBEvent first_ignored_event;
bool eof = GetNextValidEvent(trace, &event, &first_ignored_event, &sym);
// Assign the elapsed time to the previous function symbol
uint64_t elapsed = 0;
if (first_ignored_event.time != 0)
elapsed = first_ignored_event.time - prev_bb_time;
else if (!eof)
elapsed = event.time - prev_bb_time;
prev_sym->elapsed += elapsed;
if (eof)
break;
prev_bb_time = event.time;
sym->count += 1;
prev_sym = sym;
#if 0
printf("t%lld bb_num: %d, bb_addr: 0x%x func: %s, addr: 0x%x, count: %d\n",
bb_time, bb_num, bb_addr, sym->name, sym->addr, sym->count);
#endif
}
int nsyms;
symbol_type *syms = trace->GetSymbols(&nsyms);
// Sort the symbols into decreasing order of elapsed time
qsort(syms, nsyms, sizeof(symbol_type), cmp_sym_elapsed);
// Add up all the cycles
uint64_t total = 0;
symbol_type *sym = syms;
for (int ii = 0; ii < nsyms; ++ii, ++sym) {
total += sym->elapsed;
}
double secs = 1.0 * total / kMHz;
printf("Total seconds: %.2f, total cycles: %lld, MHz: %d\n\n",
secs, total, kMHz / kMillion);
uint64_t sum = 0;
printf("Elapsed secs Elapsed cyc %% %% Function\n");
sym = syms;
for (int ii = 0; ii < nsyms; ++ii, ++sym) {
if (sym->elapsed == 0)
break;
sum += sym->elapsed;
double per = 100.0 * sym->elapsed / total;
double sum_per = 100.0 * sum / total;
double secs = 1.0 * sym->elapsed / kMHz;
const char *ksym = " ";
if (sym->region->flags & region_type::kIsKernelRegion)
ksym = "k";
printf("%12.2f %11lld %6.2f %6.2f %s %s\n",
secs, sym->elapsed, per, sum_per, ksym, sym->name);
}
delete[] syms;
delete trace;
return 0;
}

View File

@@ -1,274 +0,0 @@
// Copyright 2006 The Android Open Source Project
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
#include <assert.h>
#include "trace_reader.h"
#include "bitvector.h"
#include "parse_options.h"
#include "dmtrace.h"
#include "armdis.h"
struct symbol {
uint32_t id;
};
typedef TraceReader<symbol> TraceReaderType;
#include "parse_options-inl.h"
#include "callstack.h"
DmTrace *dmtrace;
class MyFrame : public StackFrame<symbol_type> {
public:
void push(int stackLevel, uint64_t time, CallStackBase *base);
void pop(int stackLevel, uint64_t time, CallStackBase *base);
};
typedef CallStack<MyFrame> CallStackType;
static const int kNumStackFrames = 500;
static const int kMaxThreads = (32 * 1024);
uint64_t thread_time[kMaxThreads];
class FunctionStack {
public:
FunctionStack() {
top = 0;
}
void push(symbol_type *sym) {
if (top >= kNumStackFrames)
return;
frames[top] = sym;
top += 1;
}
symbol_type* pop() {
if (top <= 0) {
return NULL;
}
top -= 1;
return frames[top];
}
void showStack() {
fprintf(stderr, "top %d\n", top);
for (int ii = 0; ii < top; ii++) {
fprintf(stderr, " %d: %s\n", ii, frames[ii]->name);
}
}
private:
int top;
symbol_type *frames[kNumStackFrames];
};
FunctionStack *dmtrace_stack[kMaxThreads];
void MyFrame::push(int stackLevel, uint64_t time, CallStackBase *base)
{
int pid = base->getId();
CallStackType *stack = (CallStackType *) base;
#if 0
fprintf(stderr, "native push t %llu p %d s %d fid %d 0x%x %s\n",
stack->getGlobalTime(time), pid, stackLevel,
function->id, function->addr, function->name);
#endif
FunctionStack *fstack = dmtrace_stack[pid];
if (fstack == NULL) {
fstack = new FunctionStack();
dmtrace_stack[pid] = fstack;
}
fstack->push(function);
thread_time[pid] = time;
dmtrace->addFunctionEntry(function->id, time, pid);
}
void MyFrame::pop(int stackLevel, uint64_t time, CallStackBase *base)
{
int pid = base->getId();
CallStackType *stack = (CallStackType *) base;
#if 0
fprintf(stderr, "native pop t %llu p %d s %d fid %d 0x%x %s\n",
stack->getGlobalTime(time), pid, stackLevel,
function->id, function->addr, function->name);
#endif
FunctionStack *fstack = dmtrace_stack[pid];
if (fstack == NULL) {
fstack = new FunctionStack();
dmtrace_stack[pid] = fstack;
}
symbol_type *sym = fstack->pop();
if (sym != NULL && sym != function) {
fprintf(stderr, "Error: q2dm function mismatch at time %llu pid %d sym %s\n",
stack->getGlobalTime(time), pid, sym->name);
fstack->showStack();
exit(1);
}
thread_time[pid] = time;
dmtrace->addFunctionExit(function->id, time, pid);
}
uint32_t nextFunctionId = 4;
CallStackType *stacks[kMaxThreads];
void Usage(const char *program)
{
fprintf(stderr, "Usage: %s [options] trace_name elf_file dmtrace_name\n",
program);
OptionsUsage();
}
int main(int argc, char **argv)
{
bool useKernelStack = true;
ParseOptions(argc, argv);
if (argc - optind != 3) {
Usage(argv[0]);
exit(1);
}
char *qemu_trace_file = argv[optind++];
char *elf_file = argv[optind++];
char *dmtrace_file = argv[optind++];
TraceReaderType *trace = new TraceReaderType;
trace->Open(qemu_trace_file);
trace->SetDemangle(demangle);
trace->ReadKernelSymbols(elf_file);
trace->SetRoot(root);
TraceHeader *qheader = trace->GetHeader();
uint64_t startTime = qheader->start_sec;
startTime = (startTime << 32) | qheader->start_usec;
int kernelPid = qheader->first_unused_pid;
dmtrace = new DmTrace;
dmtrace->open(dmtrace_file, startTime);
bool inKernel = false;
CallStackType *kernelStack = NULL;
if (useKernelStack) {
// Create a fake kernel thread stack where we will put all the kernel
// code.
kernelStack = new CallStackType(kernelPid, kNumStackFrames, trace);
dmtrace->addThread(kernelPid, "(kernel)");
}
CallStackType *prevStack = NULL;
BBEvent event;
while (1) {
BBEvent ignored;
symbol_type *function;
if (GetNextValidEvent(trace, &event, &ignored, &function))
break;
if (event.bb_num == 0)
break;
#if 0
fprintf(stderr, "event t %llu p %d %s\n",
event.time, event.pid, function->name);
#endif
CallStackType *pStack;
if (useKernelStack) {
uint32_t flags = function->region->flags;
uint32_t region_mask = region_type::kIsKernelRegion
| region_type::kIsUserMappedRegion;
if ((flags & region_mask) == region_type::kIsKernelRegion) {
// Use the kernel stack
pStack = kernelStack;
inKernel = true;
} else {
// If we were just in the kernel then pop off all of the
// stack frames for the kernel thread.
if (inKernel == true) {
inKernel = false;
kernelStack->popAll(event.time);
}
// Get the stack for the current thread
pStack = stacks[event.pid];
}
} else {
// Get the stack for the current thread
pStack = stacks[event.pid];
}
// If the stack does not exist, then allocate a new one.
if (pStack == NULL) {
pStack = new CallStackType(event.pid, kNumStackFrames, trace);
stacks[event.pid] = pStack;
const char *name = trace->GetProcessName(event.pid);
dmtrace->addThread(event.pid, name);
}
if (prevStack != pStack) {
pStack->threadStart(event.time);
if (prevStack)
prevStack->threadStop(event.time);
}
prevStack = pStack;
// If we have never seen this function before, then add it to the
// list of known functions.
if (function->id == 0) {
function->id = nextFunctionId;
nextFunctionId += 4;
uint32_t flags = function->region->flags;
const char *name = function->name;
if (flags & region_type::kIsKernelRegion) {
// To distinguish kernel function names from user library
// names, add a marker to the name.
int len = strlen(name) + strlen(" [kernel]") + 1;
char *kernelName = new char[len];
strcpy(kernelName, name);
strcat(kernelName, " [kernel]");
name = kernelName;
}
dmtrace->parseAndAddFunction(function->id, name);
}
// Update the stack
pStack->updateStack(&event, function);
}
if (prevStack == NULL) {
fprintf(stderr, "Error: no events in trace.\n");
exit(1);
}
prevStack->threadStop(event.time);
for (int ii = 0; ii < kMaxThreads; ++ii) {
if (stacks[ii]) {
stacks[ii]->threadStart(event.time);
stacks[ii]->popAll(event.time);
}
}
if (useKernelStack) {
kernelStack->popAll(event.time);
}
// Read the pid events to find the names of the processes
while (1) {
PidEvent pid_event;
if (trace->ReadPidEvent(&pid_event))
break;
if (pid_event.rec_type == kPidName) {
dmtrace->updateName(pid_event.pid, pid_event.path);
}
}
dmtrace->close();
delete dmtrace;
delete trace;
return 0;
}

View File

@@ -1,108 +0,0 @@
// Copyright 2006 The Android Open Source Project
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
#include <assert.h>
#include "trace_reader.h"
#include "gtrace.h"
#include "bitvector.h"
#include "parse_options.h"
struct symbol {
int filenum; // the file number (for gtrace)
int procnum; // the procedure number (for gtrace)
};
typedef TraceReader<symbol> TraceReaderType;
#include "parse_options-inl.h"
const int kMaxProcNum = 4095;
int next_filenum = 1;
int next_procnum = 1;
void Usage(const char *program)
{
fprintf(stderr, "Usage: %s [options] trace_file elf_file gtrace_file\n",
program);
OptionsUsage();
}
int main(int argc, char **argv)
{
ParseOptions(argc, argv);
if (argc - optind != 3) {
Usage(argv[0]);
exit(1);
}
char *qemu_trace_file = argv[optind++];
char *elf_file = argv[optind++];
char *gtrace_file = argv[optind++];
TraceReader<symbol> *trace = new TraceReader<symbol>;
trace->Open(qemu_trace_file);
trace->ReadKernelSymbols(elf_file);
trace->SetRoot(root);
TraceHeader *qheader = trace->GetHeader();
// Get the first valid event to get the process id for the gtrace header.
BBEvent event;
BBEvent ignored;
symbol_type *sym;
if (GetNextValidEvent(trace, &event, &ignored, &sym))
return 0;
Gtrace *gtrace = new Gtrace;
gtrace->Open(gtrace_file, qheader->pdate, qheader->ptime);
gtrace->WriteFirstHeader(qheader->start_sec, event.pid);
symbol_type *prev_sym = NULL;
bool eof = false;
while (!eof) {
if (sym != prev_sym) {
// This procedure is different from the previous procedure.
// If we have never seen this symbol before, then add it to the
// list of known procedures.
if (sym->filenum == 0) {
sym->filenum = next_filenum;
sym->procnum = next_procnum;
gtrace->AddProcedure(sym->filenum, sym->procnum, sym->name);
next_procnum += 1;
if (next_procnum > kMaxProcNum) {
next_filenum += 1;
next_procnum = 1;
}
}
// If we haven't yet recorded the procedure exit for the previous
// procedure, then do it now.
if (prev_sym) {
gtrace->AddProcExit(prev_sym->filenum, prev_sym->procnum, event.time,
event.pid);
}
// If this is not the terminating record, then record a procedure
// entry.
if (event.bb_num != 0) {
gtrace->AddProcEntry(sym->filenum, sym->procnum, event.time, event.pid);
prev_sym = sym;
}
}
eof = GetNextValidEvent(trace, &event, &ignored, &sym);
if (ignored.time != 0 && prev_sym) {
// We read an event that we are ignoring.
// If we haven't already recorded a procedure exit, then do so.
gtrace->AddProcExit(prev_sym->filenum, prev_sym->procnum, ignored.time,
ignored.pid);
prev_sym = NULL;
}
}
delete gtrace;
delete trace;
return 0;
}

View File

@@ -1,29 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "trace_reader.h"
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s trace_file\n", argv[0]);
exit(1);
}
char *trace_filename = argv[1];
TraceReaderBase *trace = new TraceReaderBase;
trace->Open(trace_filename);
while (1) {
uint64_t time;
uint32_t addr;
int flags;
if (trace->ReadAddr(&time, &addr, &flags))
break;
const char *op = "ld";
if (flags == 1)
op = "st";
printf("%lld 0x%08x %s\n", time, addr, op);
}
return 0;
}

View File

@@ -1,210 +0,0 @@
/*************************************************************************
Copyright (C) 2002,2003,2004,2005 Wei Qin
See file COPYING for more information.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "read_elf.h"
#define SwapHalf(a) (((a & 0x00ff) << 8) | ((a & 0xff00) >> 8))
#define SwapWord(a) (((a & 0xff000000) >> 24) | ((a & 0x00ff0000) >> 8) | ((a & 0x0000ff00) << 8) | ((a & 0x000000ff) << 24))
#define SwapAddr(a) SwapWord(a)
#define SwapOff(a) SwapWord(a)
#define SwapSection(a) SwapHalf(a)
int LittleEndian()
{
Elf32_Word a = 0x01020304;
return *(char *) &a == 0x04;
}
void SwapElfHeader(Elf32_Ehdr *hdr)
{
hdr->e_type = SwapHalf(hdr->e_type);
hdr->e_machine = SwapHalf(hdr->e_machine);
hdr->e_version = SwapWord(hdr->e_version);
hdr->e_entry = SwapAddr(hdr->e_entry);
hdr->e_phoff = SwapOff(hdr->e_phoff);
hdr->e_shoff = SwapOff(hdr->e_shoff);
hdr->e_flags = SwapWord(hdr->e_flags);
hdr->e_ehsize = SwapHalf(hdr->e_ehsize);
hdr->e_phentsize = SwapHalf(hdr->e_phentsize);
hdr->e_phnum = SwapHalf(hdr->e_phnum);
hdr->e_shentsize = SwapHalf(hdr->e_shentsize);
hdr->e_shnum = SwapHalf(hdr->e_shnum);
hdr->e_shstrndx = SwapHalf(hdr->e_shstrndx);
}
void SwapSectionHeader(Elf32_Shdr *shdr)
{
shdr->sh_name = SwapWord(shdr->sh_name);
shdr->sh_type = SwapWord(shdr->sh_type);
shdr->sh_flags = SwapWord(shdr->sh_flags);
shdr->sh_addr = SwapAddr(shdr->sh_addr);
shdr->sh_offset = SwapOff(shdr->sh_offset);
shdr->sh_size = SwapWord(shdr->sh_size);
shdr->sh_link = SwapWord(shdr->sh_link);
shdr->sh_info = SwapWord(shdr->sh_info);
shdr->sh_addralign = SwapWord(shdr->sh_addralign);
shdr->sh_entsize = SwapWord(shdr->sh_entsize);
}
void SwapElfSymbol(Elf32_Sym *sym)
{
sym->st_name = SwapWord(sym->st_name);
sym->st_value = SwapAddr(sym->st_value);
sym->st_size = SwapWord(sym->st_size);
sym->st_shndx = SwapSection(sym->st_shndx);
}
void AdjustElfHeader(Elf32_Ehdr *hdr)
{
switch(hdr->e_ident[EI_DATA])
{
case ELFDATA2LSB:
if (!LittleEndian())
SwapElfHeader(hdr);
break;
case ELFDATA2MSB:
if (LittleEndian())
SwapElfHeader(hdr);
break;
}
}
void AdjustSectionHeader(Elf32_Ehdr *hdr, Elf32_Shdr *shdr)
{
switch(hdr->e_ident[EI_DATA])
{
case ELFDATA2LSB:
if (!LittleEndian())
SwapSectionHeader(shdr);
break;
case ELFDATA2MSB:
if (LittleEndian())
SwapSectionHeader(shdr);
break;
}
}
void AdjustElfSymbols(Elf32_Ehdr *hdr, Elf32_Sym *elf_symbols, int num_entries)
{
if (hdr->e_ident[EI_DATA] == ELFDATA2LSB && LittleEndian())
return;
if (hdr->e_ident[EI_DATA] == ELFDATA2MSB && !LittleEndian())
return;
for (int ii = 0; ii < num_entries; ++ii) {
SwapElfSymbol(&elf_symbols[ii]);
}
}
Elf32_Ehdr *ReadElfHeader(FILE *fobj)
{
Elf32_Ehdr *hdr = new Elf32_Ehdr;
int rval = fread(hdr, sizeof(Elf32_Ehdr), 1, fobj);
if (rval != 1) {
delete hdr;
return NULL;
}
if (hdr->e_ident[EI_MAG0] != 0x7f || hdr->e_ident[EI_MAG1] != 'E' ||
hdr->e_ident[EI_MAG2] != 'L' || hdr->e_ident[EI_MAG3] != 'F') {
delete hdr;
return NULL;
}
AdjustElfHeader(hdr);
return hdr;
}
Elf32_Shdr *ReadSectionHeaders(Elf32_Ehdr *hdr, FILE *f)
{
int i;
unsigned long sz = hdr->e_shnum * hdr->e_shentsize;
assert(sizeof(Elf32_Shdr) == hdr->e_shentsize);
Elf32_Shdr *shdr = new Elf32_Shdr[hdr->e_shnum];
if (fseek(f, hdr->e_shoff, SEEK_SET) != 0)
{
delete[] shdr;
return NULL;
}
if (fread(shdr, sz, 1, f) != 1)
{
delete[] shdr;
return NULL;
}
for(i = 0; i < hdr->e_shnum; i++)
AdjustSectionHeader(hdr, shdr + i);
return shdr;
}
char *ReadStringTable(Elf32_Ehdr *hdr, Elf32_Shdr *shdr_table, FILE *f)
{
Elf32_Shdr *shdr = shdr_table + hdr->e_shstrndx;
char *string_table;
string_table = new char[shdr->sh_size];
fseek(f, shdr->sh_offset, SEEK_SET);
fread(string_table, shdr->sh_size, 1, f);
return string_table;
}
int ReadSection(Elf32_Shdr *shdr, void *buffer, FILE *f)
{
if (fseek(f, shdr->sh_offset, SEEK_SET) != 0)
return -1;
if (fread(buffer, shdr->sh_size, 1, f) != 1)
return -1;
return 0;
}
char *GetSymbolName(Elf32_Half index, char *string_table)
{
return string_table + index;
}
Elf32_Shdr *FindSymbolTableSection(Elf32_Ehdr *hdr,
Elf32_Shdr *shdr,
char *string_table)
{
for(int ii = 0; ii < hdr->e_shnum; ii++) {
if (shdr[ii].sh_type == SHT_SYMTAB &&
strcmp(GetSymbolName(shdr[ii].sh_name, string_table),
".symtab") == 0)
{
return &shdr[ii];
}
}
return NULL;
}
Elf32_Shdr *FindSymbolStringTableSection(Elf32_Ehdr *hdr,
Elf32_Shdr *shdr,
char *string_table)
{
for(int ii = 0; ii < hdr->e_shnum; ii++) {
if (shdr[ii].sh_type == SHT_STRTAB &&
strcmp(GetSymbolName(shdr[ii].sh_name, string_table),
".strtab") == 0)
{
return &shdr[ii];
}
}
return NULL;
}

View File

@@ -1,20 +0,0 @@
#ifndef READ_ELF_H
#define READ_ELF_H
#include <stdio.h>
#include <elf.h>
Elf32_Ehdr *ReadElfHeader(FILE *fobj);
Elf32_Shdr *ReadSectionHeaders(Elf32_Ehdr *hdr, FILE *fobj);
char *ReadStringTable(Elf32_Ehdr *hdr, Elf32_Shdr *shdr, FILE *fobj);
Elf32_Shdr *FindSymbolTableSection(Elf32_Ehdr *hdr,
Elf32_Shdr *shdr,
char *string_table);
Elf32_Shdr *FindSymbolStringTableSection(Elf32_Ehdr *hdr,
Elf32_Shdr *shdr,
char *string_table);
int ReadSection(Elf32_Shdr *shdr, void *buffer, FILE *f);
void AdjustElfSymbols(Elf32_Ehdr *hdr, Elf32_Sym *elf_symbols,
int num_entries);
#endif /* READ_ELF_H */

View File

@@ -1,137 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
#include "trace_reader.h"
#include "parse_options.h"
typedef TraceReader<> TraceReaderType;
#include "parse_options-inl.h"
struct frame {
uint64_t time;
uint32_t addr;
const char *name;
bool isNative;
frame(uint64_t time, uint32_t addr, const char *name, bool isNative) {
this->time = time;
this->addr = addr;
this->name = name;
this->isNative = isNative;
}
};
class Stack {
static const int kMaxFrames = 1000;
int top;
frame *frames[kMaxFrames];
public:
Stack() {
top = 0;
}
void push(frame *pframe);
frame* pop();
void dump();
};
void Stack::push(frame *pframe) {
if (top == kMaxFrames) {
fprintf(stderr, "Error: stack overflow\n");
exit(1);
}
frames[top] = pframe;
top += 1;
}
frame *Stack::pop() {
if (top <= 0)
return NULL;
top -= 1;
return frames[top];
}
void Stack::dump() {
frame *pframe;
for (int ii = 0; ii < top; ii++) {
pframe = frames[ii];
const char *native = pframe->isNative ? "n" : " ";
printf(" %s %d: %llu 0x%x %s\n",
native, ii, pframe->time, pframe->addr,
pframe->name == NULL ? "" : pframe->name);
}
}
static const int kMaxThreads = (32 * 1024);
Stack *stacks[kMaxThreads];
void Usage(const char *program)
{
fprintf(stderr, "Usage: %s [options] trace_name elf_file\n",
program);
OptionsUsage();
}
int main(int argc, char **argv) {
ParseOptions(argc, argv);
if (argc - optind != 2) {
Usage(argv[0]);
exit(1);
}
char *qemu_trace_file = argv[optind++];
char *elf_file = argv[optind++];
TraceReaderType *trace = new TraceReaderType;
trace->Open(qemu_trace_file);
trace->ReadKernelSymbols(elf_file);
trace->SetRoot(root);
while (1) {
MethodRec method_record;
symbol_type *sym;
TraceReaderType::ProcessState *proc;
frame *pframe;
if (trace->ReadMethodSymbol(&method_record, &sym, &proc))
break;
if (!IsValidPid(proc->pid))
continue;
if (sym != NULL) {
printf("%lld p %d 0x%x %d %s\n",
method_record.time, proc->pid, method_record.addr,
method_record.flags, sym->name);
} else {
printf("%lld p %d 0x%x %d\n",
method_record.time, proc->pid, method_record.addr,
method_record.flags);
}
// Get the stack for the current thread
Stack *pStack = stacks[proc->pid];
// If the stack does not exist, then allocate a new one.
if (pStack == NULL) {
pStack = new Stack();
stacks[proc->pid] = pStack;
}
int flags = method_record.flags;
if (flags == kMethodEnter || flags == kNativeEnter) {
pframe = new frame(method_record.time, method_record.addr,
sym == NULL ? NULL: sym->name,
method_record.flags == kNativeEnter);
pStack->push(pframe);
} else {
pframe = pStack->pop();
delete pframe;
}
pStack->dump();
}
return 0;
}

View File

@@ -1,71 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "trace_reader.h"
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s trace_file\n", argv[0]);
exit(1);
}
char *trace_filename = argv[1];
TraceReaderBase *trace = new TraceReaderBase;
trace->Open(trace_filename);
while (1) {
PidEvent event;
if (trace->ReadPidEvent(&event))
break;
switch (event.rec_type) {
case kPidFork:
printf("t%lld fork tgid %d pid %d\n", event.time, event.tgid, event.pid);
break;
case kPidClone:
printf("t%lld clone tgid %d pid %d\n", event.time, event.tgid, event.pid);
break;
case kPidSwitch:
printf("t%lld switch %d\n", event.time, event.pid);
break;
case kPidExit:
printf("t%lld exit %d\n", event.time, event.pid);
break;
case kPidMmap:
printf("t%lld mmap %08x - %08x, offset %08x '%s'\n",
event.time, event.vstart, event.vend, event.offset, event.path);
delete[] event.path;
break;
case kPidMunmap:
printf("t%lld munmap %08x - %08x\n",
event.time, event.vstart, event.vend);
break;
case kPidSymbolAdd:
printf("t%lld add sym %08x '%s'\n",
event.time, event.vstart, event.path);
delete[] event.path;
break;
case kPidSymbolRemove:
printf("t%lld remove %08x\n", event.time, event.vstart);
break;
case kPidExec:
printf("t%lld argc: %d\n", event.time, event.argc);
for (int ii = 0; ii < event.argc; ++ii) {
printf(" argv[%d]: %s\n", ii, event.argv[ii]);
delete[] event.argv[ii];
}
delete[] event.argv;
break;
case kPidKthreadName:
printf("t%lld kthread tgid %d pid %d %s\n",
event.time, event.tgid, event.pid, event.path);
delete[] event.path;
break;
case kPidName:
printf("t%lld name %d %s\n",
event.time, event.pid, event.path);
delete[] event.path;
break;
}
}
return 0;
}

View File

@@ -1,165 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
#include <assert.h>
#include "trace_reader.h"
#include "armdis.h"
#include "parse_options.h"
typedef TraceReader<> TraceReaderType;
#include "parse_options-inl.h"
static const uint32_t kOffsetThreshold = 0x100000;
static uint64_t startTime = 0;
void Usage(const char *program)
{
fprintf(stderr,
"Usage: %s [options] [-- -s start_time] trace_file elf_file\n",
program);
OptionsUsage();
}
bool localParseOptions(int argc, char **argv)
{
bool err = false;
while (!err) {
int opt = getopt(argc, argv, "+s:");
if (opt == -1)
break;
switch (opt) {
case 's':
startTime = strtoull(optarg, NULL, 0);
break;
default:
err = true;
break;
}
}
return err;
}
int main(int argc, char **argv) {
// Parse the options
ParseOptions(argc, argv);
localParseOptions(argc, argv);
if (argc - optind != 2) {
Usage(argv[0]);
exit(1);
}
char *trace_filename = argv[optind++];
char *elf_file = argv[optind++];
TraceReader<> *trace = new TraceReader<>;
trace->Open(trace_filename);
trace->SetDemangle(demangle);
trace->ReadKernelSymbols(elf_file);
trace->SetRoot(root);
while (1) {
symbol_type *sym;
char buf[1024];
BBEvent event;
BBEvent ignored;
if (GetNextValidEvent(trace, &event, &ignored, &sym))
break;
#if 0
fprintf(stderr, "t%llu bb %lld %d\n",
event.time, event.bb_num, event.num_insns);
#endif
uint32_t *insns = event.insns;
uint32_t addr = event.bb_addr;
uint32_t offset = addr - sym->addr - sym->region->base_addr;
symbol_type *vm_sym = sym->vm_sym;
const char *vm_name = NULL;
if (vm_sym != NULL) {
vm_name = vm_sym->name;
offset = addr - vm_sym->addr - vm_sym->region->base_addr;
}
#if 0
if (strcmp(sym->name, "(unknown)") == 0 || offset > kOffsetThreshold) {
ProcessState *process = trace->GetCurrentProcess();
ProcessState *manager = process->addr_manager;
for (int ii = 0; ii < manager->nregions; ++ii) {
printf(" %2d: %08x - %08x base: %08x offset: %u nsyms: %4d flags: 0x%x %s\n",
ii,
manager->regions[ii]->vstart,
manager->regions[ii]->vend,
manager->regions[ii]->base_addr,
manager->regions[ii]->file_offset,
manager->regions[ii]->nsymbols,
manager->regions[ii]->flags,
manager->regions[ii]->path);
int nsymbols = manager->regions[ii]->nsymbols;
for (int jj = 0; jj < 10 && jj < nsymbols; ++jj) {
printf(" %08x %s\n",
manager->regions[ii]->symbols[jj].addr,
manager->regions[ii]->symbols[jj].name);
}
}
}
#endif
#if 1
for (int ii = 0; ii < event.num_insns; ++ii) {
uint64_t sim_time = trace->ReadInsnTime(event.time);
if (sim_time < startTime)
continue;
uint32_t insn = insns[ii];
char *disasm;
int bytes;
if (vm_name != NULL) {
sprintf(buf, "%s+%02x: %s", vm_name, offset, sym->name);
} else {
sprintf(buf, "%s+%02x", sym->name, offset);
}
if (insn_is_thumb(insn)) {
bytes = 2;
insn = insn_unwrap_thumb(insn);
// thumb_pair is true if this is the first of a pair of
// thumb instructions (BL or BLX).
bool thumb_pair = ((insn & 0xf800) == 0xf000);
// Get the next thumb instruction (if any) because we may need
// it for the case where insn is BL or BLX.
uint32_t insn2 = 0;
if (thumb_pair && (ii + 1 < event.num_insns)) {
insn2 = insns[ii + 1];
insn2 = insn_unwrap_thumb(insn2);
bytes = 4;
ii += 1;
}
disasm = disasm_insn_thumb(addr, insn, insn2, NULL);
if (thumb_pair) {
printf("%llu p%-4d %08x %04x %04x %-30s %s\n",
sim_time, event.pid, addr, insn, insn2, buf, disasm);
} else {
printf("%llu p%-4d %08x %04x %-30s %s\n",
sim_time, event.pid, addr, insn, buf, disasm);
}
} else {
bytes = 4;
disasm = Arm::disasm(addr, insn, NULL);
printf("%llu p%-4d %08x %08x %-30s %s\n",
sim_time, event.pid, addr, insn, buf, disasm);
}
//printf("t%llu \t%08x\n", sim_time, addr);
addr += bytes;
offset += bytes;
}
#endif
#if 0
assert(offset < kOffsetThreshold);
#endif
}
delete trace;
return 0;
}

View File

@@ -1,156 +0,0 @@
// Copyright 2006 The Android Open Source Project
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
#include <assert.h>
#include "trace_reader.h"
#include "bitvector.h"
#include "parse_options.h"
#include "armdis.h"
typedef TraceReader<> TraceReaderType;
#include "parse_options-inl.h"
#include "callstack.h"
static uint64_t debugTime;
static uint64_t dumpTime = 0;
class MyFrame : public StackFrame<symbol_type> {
public:
void push(int stackLevel, uint64_t time, CallStackBase *base);
void pop(int stackLevel, uint64_t time, CallStackBase *base);
void getFrameType(char *type);
};
typedef CallStack<MyFrame> CallStackType;
void MyFrame::getFrameType(char *type)
{
strcpy(type, "----");
if (flags & kCausedException)
type[0] = 'e';
if (flags & kInterpreted)
type[1] = 'm';
if (function->region->flags & region_type::kIsKernelRegion)
type[2] = 'k';
if (function->flags & symbol_type::kIsVectorTable)
type[3] = 'v';
}
void MyFrame::push(int stackLevel, uint64_t time, CallStackBase *base)
{
char type[5];
if (dumpTime > 0)
return;
getFrameType(type);
printf("%llu en thr %d %s %3d", time, base->getId(), type, stackLevel);
for (int ii = 0; ii < stackLevel; ++ii)
printf(".");
printf(" 0x%08x %s\n", addr, function->name);
}
void MyFrame::pop(int stackLevel, uint64_t time, CallStackBase *base)
{
char type[5];
if (dumpTime > 0)
return;
getFrameType(type);
printf("%llu x thr %d %s %3d", time, base->getId(), type, stackLevel);
for (int ii = 0; ii < stackLevel; ++ii)
printf(".");
printf(" 0x%08x %s\n", addr, function->name);
}
static const int kNumStackFrames = 500;
static const int kMaxThreads = (32 * 1024);
CallStackType *stacks[kMaxThreads];
void Usage(const char *program)
{
fprintf(stderr, "Usage: %s [options] [-- -d dumpTime] trace_name elf_file\n",
program);
OptionsUsage();
}
bool localParseOptions(int argc, char **argv)
{
bool err = false;
while (!err) {
int opt = getopt(argc, argv, "+d:");
if (opt == -1)
break;
switch (opt) {
case 'd':
dumpTime = strtoull(optarg, NULL, 0);
break;
default:
err = true;
break;
}
}
return err;
}
int main(int argc, char **argv)
{
ParseOptions(argc, argv);
localParseOptions(argc, argv);
if (argc - optind != 2) {
Usage(argv[0]);
exit(1);
}
char *qemu_trace_file = argv[optind++];
char *elf_file = argv[optind++];
TraceReaderType *trace = new TraceReaderType;
trace->Open(qemu_trace_file);
trace->ReadKernelSymbols(elf_file);
trace->SetRoot(root);
BBEvent event;
while (1) {
BBEvent ignored;
symbol_type *function;
if (GetNextValidEvent(trace, &event, &ignored, &function))
break;
if (event.bb_num == 0)
break;
// Get the stack for the current thread
CallStackType *pStack = stacks[event.pid];
// If the stack does not exist, then allocate a new one.
if (pStack == NULL) {
pStack = new CallStackType(event.pid, kNumStackFrames, trace);
stacks[event.pid] = pStack;
}
if (debugTime != 0 && event.time >= debugTime)
printf("debug time: %lld\n", debugTime);
// Update the stack
pStack->updateStack(&event, function);
// If the user requested a stack dump at a certain time,
// and we are at that time, then dump the stack and exit.
if (dumpTime > 0 && event.time >= dumpTime) {
pStack->showStack(stdout);
break;
}
}
for (int ii = 0; ii < kMaxThreads; ++ii) {
if (stacks[ii])
stacks[ii]->popAll(event.time);
}
delete trace;
return 0;
}

View File

@@ -1,25 +0,0 @@
CC := arm-elf-gcc
LD := arm-elf-ld
AS := arm-elf-as
OBJCOPY := arm-elf-objcopy
OBJDUMP := arm-elf-objdump
OPT := -g
CFLAGS := $(OPT) -mcpu=arm9
.SUFFIXES: .dis .bin .elf
.c.elf:
$(CC) $(CFLAGS) -Xlinker --script ../tests.ld -o $@ $< -nostdlib
.c.s:
$(CC) $(CFLAGS) -static -S $<
.S.elf:
$(CC) $(CFLAGS) -Xlinker --script ../tests.ld -nostdlib -o $@ $<
.elf.dis:
$(OBJDUMP) -adx $< > $@
.elf.bin:
$(OBJCOPY) -O binary $< $@

View File

@@ -1,3 +0,0 @@
clean:
rm -f *.elf *.dis *.bin *.o *~ a.out

View File

@@ -1,18 +0,0 @@
include ../common_head.mk
P4ROOT=/work/android
QEMU=$(P4ROOT)/device/tools/qemu/arm-softmmu/qemu-system-arm
QTOOLS=$(P4ROOT)/device/tools/qtools
all: test.elf test.bin test.dis
trace: test.elf test.bin
$(QEMU) -QEMU -kernel test.bin -trace foo
$(QTOOLS)/post_trace foo
$(QTOOLS)/read_trace foo test.elf > t1
gtrace: trace
$(QTOOLS)/q2g -r $(P4ROOT)/device/out/linux-arm-release/symbols foo test.elf foo.gtrace
gtracepost64 foo.gtrace > t2
include ../common_tail.mk

View File

@@ -1,201 +0,0 @@
#include "../macros.h"
int foo1();
int foo2();
void bar();
int child1();
int child2();
int child3();
int child4();
int child5();
int global;
void start()
{
// Set the stack pointer
asm(" mov r13,#0x200000");
PRINT_STR("hello\n");
TRACE_INIT_NAME(701, "proc_foo");
TRACE_INIT_NAME(702, "proc_bar");
TRACE_SWITCH(701);
if (global++ > 0)
global++;
foo1();
TRACE_SWITCH(702);
if (global++ > 0)
global++;
bar();
TRACE_SWITCH(701);
if (global++ > 0)
global++;
foo2();
TRACE_SWITCH(703);
if (global++ > 0)
global++;
foo1();
TRACE_SWITCH(701);
if (global++ > 0)
global++;
foo1();
TRACE_SWITCH(704);
if (global++ > 0)
global++;
foo1();
TRACE_SWITCH(701);
if (global++ > 0)
global++;
foo1();
TRACE_SWITCH(705);
if (global++ > 0)
global++;
foo1();
TRACE_SWITCH(701);
if (global++ > 0)
global++;
foo1();
TRACE_SWITCH(706);
if (global++ > 0)
global++;
foo1();
TRACE_SWITCH(701);
if (global++ > 0)
global++;
foo1();
TRACE_SWITCH(707);
if (global++ > 0)
global++;
foo1();
TRACE_SWITCH(701);
if (global++ > 0)
global++;
foo1();
TRACE_SWITCH(708);
if (global++ > 0)
global++;
foo1();
TRACE_SWITCH(701);
if (global++ > 0)
global++;
foo1();
TRACE_SWITCH(709);
if (global++ > 0)
global++;
foo1();
TRACE_SWITCH(701);
if (global++ > 0)
global++;
foo1();
TRACE_SWITCH(710);
if (global++ > 0)
global++;
foo1();
TRACE_STOP_EMU();
}
int foo1()
{
int a = 0;
int ii;
for (ii = 0; ii < 3; ++ii) {
a += child1();
a += child2();
a += child3();
}
return a;
}
int foo2()
{
int a = 0;
int ii;
for (ii = 0; ii < 2; ++ii) {
a += child3();
a += child4();
a += child5();
}
return a;
}
#define kStride 64
void bar()
{
int a = 0;
static char mem[1000 * kStride];
int ii, jj;
for (ii = 0; ii < 4; ++ii) {
for (jj = 0; jj < 10; ++jj)
a += mem[jj * kStride];
foo1();
foo2();
}
}
int child1()
{
int a = 0;
int ii;
for (ii = 0; ii < 2; ++ii)
a += ii;
return a;
}
int child2()
{
int a = 0;
int ii;
for (ii = 0; ii < 4; ++ii)
a += ii;
return a;
}
int child3()
{
int a = 0;
int ii;
for (ii = 0; ii < 6; ++ii)
a += ii;
return a;
}
int child4()
{
int a = 0;
int ii;
for (ii = 0; ii < 8; ++ii)
a += ii;
return a;
}
int child5()
{
int a = 0;
int ii;
for (ii = 0; ii < 10; ++ii)
a += ii;
return a;
}

View File

@@ -1,93 +0,0 @@
#ifndef _TEST_TRACE_C_H_
#define _TEST_TRACE_C_H_
/* the base address of trace device */
#define TRACE_DEV_BASE_ADDR 0x21000000
/*the register addresses of the trace device */
#define TRACE_DEV_REG_SWITCH 0
#define TRACE_DEV_REG_FORK 1
#define TRACE_DEV_REG_EXECVE_PID 2
#define TRACE_DEV_REG_EXECVE_VMSTART 3
#define TRACE_DEV_REG_EXECVE_VMEND 4
#define TRACE_DEV_REG_EXECVE_OFFSET 5
#define TRACE_DEV_REG_EXECVE_EXEPATH 6
#define TRACE_DEV_REG_EXIT 7
#define TRACE_DEV_REG_CMDLINE 8
#define TRACE_DEV_REG_CMDLINE_LEN 9
#define TRACE_DEV_REG_MMAP_EXEPATH 10
#define TRACE_DEV_REG_INIT_PID 11
#define TRACE_DEV_REG_INIT_NAME 12
#define TRACE_DEV_REG_CLONE 13
#define TRACE_DEV_REG_DYN_SYM 50
#define TRACE_DEV_REG_DYN_SYM_ADDR 51
#define TRACE_DEV_REG_PRINT_STR 60
#define TRACE_DEV_REG_PRINT_NUM_DEC 61
#define TRACE_DEV_REG_PRINT_NUM_HEX 62
#define TRACE_DEV_REG_STOP_EMU 90
#define TRACE_DEV_REG_ENABLE 100
#define TRACE_DEV_REG_DISABLE 101
/* write a word to a trace device register */
#define DEV_WRITE_WORD(addr,value)\
(*(volatile unsigned long *)(TRACE_DEV_BASE_ADDR + ((addr) << 2)) = (value))
/*************************************************************/
/* generates test events */
/* context switch */
#define TRACE_SWITCH(pid) DEV_WRITE_WORD(TRACE_DEV_REG_SWITCH, (pid))
/* fork */
#define TRACE_FORK(pid) DEV_WRITE_WORD(TRACE_DEV_REG_FORK, (pid))
/* clone */
#define TRACE_CLONE(pid) DEV_WRITE_WORD(TRACE_DEV_REG_CLONE, (pid))
/* dump name and path of threads executed before trace device created */
#define TRACE_INIT_NAME(pid,path)\
do {\
DEV_WRITE_WORD(TRACE_DEV_REG_INIT_PID, (pid));\
DEV_WRITE_WORD(TRACE_DEV_REG_INIT_NAME, (unsigned long)(path));\
}while(0)
/* dump exec mapping of threads executed before trace device created */
#define TRACE_INIT_EXEC(vstart,vend,eoff,path)\
do {\
DEV_WRITE_WORD(TRACE_DEV_REG_EXECVE_VMSTART, (vstart));\
DEV_WRITE_WORD(TRACE_DEV_REG_EXECVE_VMEND, (vend));\
DEV_WRITE_WORD(TRACE_DEV_REG_EXECVE_OFFSET, (eoff));\
DEV_WRITE_WORD(TRACE_DEV_REG_EXECVE_EXEPATH, (unsigned long)(path));\
}while(0)
/* mmap */
#define TRACE_MMAP(vstart,vend,eoff,path)\
do {\
DEV_WRITE_WORD(TRACE_DEV_REG_EXECVE_VMSTART, (vstart));\
DEV_WRITE_WORD(TRACE_DEV_REG_EXECVE_VMEND, (vend));\
DEV_WRITE_WORD(TRACE_DEV_REG_EXECVE_OFFSET, (eoff));\
DEV_WRITE_WORD(TRACE_DEV_REG_MMAP_EXEPATH, (unsigned long)(path));\
}while(0)
/* execve */
#define TRACE_EXECVE(cmdlen,cmd)\
do {\
DEV_WRITE_WORD(TRACE_DEV_REG_CMDLINE_LEN, (cmdlen));\
DEV_WRITE_WORD(TRACE_DEV_REG_CMDLINE, (unsigned long)(cmd));\
}while(0)
/* exit */
#define TRACE_EXIT(retv) DEV_WRITE_WORD(TRACE_DEV_REG_EXIT, (retv))
/* other commands */
/* stop emulation */
#define TRACE_STOP_EMU() DEV_WRITE_WORD(TRACE_DEV_REG_STOP_EMU, 1)
/* enable/disable tracing */
#define TRACE_ENABLE_TRACING() DEV_WRITE_WORD(TRACE_DEV_REG_ENABLE, 1)
#define TRACE_DISABLE_TRACING() DEV_WRITE_WORD(TRACE_DEV_REG_DISABLE, 1)
/* dynamic symbols */
#define TRACE_DYN_SYM(addr,sym)\
do {\
DEV_WRITE_WORD(TRACE_DEV_REG_DYN_SYM_ADDR, (addr));\
DEV_WRITE_WORD(TRACE_DEV_REG_DYN_SYM, (unsigned long)(sym));\
}while(0)
/* prints */
#define PRINT_STR(str) DEV_WRITE_WORD(TRACE_DEV_REG_PRINT_STR, (unsigned long)(str))
#define PRINT_NUM_DEC(num) DEV_WRITE_WORD(TRACE_DEV_REG_PRINT_NUM_DEC, (num))
#define PRINT_NUM_HEX(num) DEV_WRITE_WORD(TRACE_DEV_REG_PRINT_NUM_HEX, (num))
#endif

View File

@@ -1,10 +0,0 @@
SECTIONS {
TEXT_START = 0x00010000 ;
DATA_START = 0x00200000 ;
handlers 0x0 : { *(handlers) }
.text TEXT_START : { *(.text) }
.data DATA_START : { *(.data) }
.bss : { *(.bss) *(COMMON) }
p00300000 0x00300000 : { *(p00300000) }
p00400000 0x00400000 : { *(p00400000) }
}

View File

@@ -1,503 +0,0 @@
/* Instruction printing code for the ARM
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
Modification by James G. Smith (jsmith@cygnus.co.uk)
This file is part of libopcodes.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Modified to fit into the qtools framework. The main differences are:
*
* - The disassembly function returns a string instead of writing it to a
* file stream.
*
* - All the references to the struct "disassemble_info" have been removed.
*
* - A set of enums for the thumb opcodes have been defined, along with a
* "decode()" function that maps a thumb instruction to an opcode enum.
*
* - Eliminated uses of the special characters ', `, and ? from the
* thumb_opcodes[] table so that we can easily specify separate opcodes
* for distinct instructions.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "opcode.h"
struct thumb_opcode
{
unsigned short value, mask; /* recognise instruction if (op&mask)==value */
Opcode opcode;
const char * assembler; /* how to disassemble this instruction */
};
/* format of the assembler string :
%% %
%<bitfield>d print the bitfield in decimal
%<bitfield>x print the bitfield in hex
%<bitfield>X print the bitfield as 1 hex digit without leading "0x"
%<bitfield>r print as an ARM register
%<bitfield>f print a floating point constant if >7 else a
floating point register
%<code>y print a single precision VFP reg.
Codes: 0=>Sm, 1=>Sd, 2=>Sn, 3=>multi-list, 4=>Sm pair
%<code>z print a double precision VFP reg
Codes: 0=>Dm, 1=>Dd, 2=>Dn, 3=>multi-list
%c print condition code (always bits 28-31)
%P print floating point precision in arithmetic insn
%Q print floating point precision in ldf/stf insn
%R print floating point rounding mode
%<bitnum>'c print specified char iff bit is one
%<bitnum>`c print specified char iff bit is zero
%<bitnum>?ab print a if bit is one else print b
%p print 'p' iff bits 12-15 are 15
%t print 't' iff bit 21 set and bit 24 clear
%o print operand2 (immediate or register + shift)
%a print address for ldr/str instruction
%s print address for ldr/str halfword/signextend instruction
%b print branch destination
%B print arm BLX(1) destination
%A print address for ldc/stc/ldf/stf instruction
%m print register mask for ldm/stm instruction
%C print the PSR sub type.
%F print the COUNT field of a LFM/SFM instruction.
Thumb specific format options:
%D print Thumb register (bits 0..2 as high number if bit 7 set)
%S print Thumb register (bits 3..5 as high number if bit 6 set)
%<bitfield>I print bitfield as a signed decimal
(top bit of range being the sign bit)
%M print Thumb register mask
%N print Thumb register mask (with LR)
%O print Thumb register mask (with PC)
%T print Thumb condition code (always bits 8-11)
%I print cirrus signed shift immediate: bits 0..3|4..6
%<bitfield>B print Thumb branch destination (signed displacement)
%<bitfield>W print (bitfield * 4) as a decimal
%<bitfield>H print (bitfield * 2) as a decimal
%<bitfield>a print (bitfield * 4) as a pc-rel offset + decoded symbol
*/
static struct thumb_opcode thumb_opcodes[] =
{
/* Thumb instructions. */
/* ARM V5 ISA extends Thumb. */
{0xbe00, 0xff00, OP_THUMB_BKPT, "bkpt\t%0-7x"},
{0x4780, 0xff87, OP_THUMB_BLX, "blx\t%3-6r"}, /* note: 4 bit register number. */
/* Format 5 instructions do not update the PSR. */
{0x1C00, 0xFFC0, OP_THUMB_MOV, "mov\t%0-2r, %3-5r"},
/* Format 4. */
{0x4000, 0xFFC0, OP_THUMB_AND, "and\t%0-2r, %3-5r"},
{0x4040, 0xFFC0, OP_THUMB_EOR, "eor\t%0-2r, %3-5r"},
{0x4080, 0xFFC0, OP_THUMB_LSL, "lsl\t%0-2r, %3-5r"},
{0x40C0, 0xFFC0, OP_THUMB_LSR, "lsr\t%0-2r, %3-5r"},
{0x4100, 0xFFC0, OP_THUMB_ASR, "asr\t%0-2r, %3-5r"},
{0x4140, 0xFFC0, OP_THUMB_ADC, "adc\t%0-2r, %3-5r"},
{0x4180, 0xFFC0, OP_THUMB_SBC, "sbc\t%0-2r, %3-5r"},
{0x41C0, 0xFFC0, OP_THUMB_ROR, "ror\t%0-2r, %3-5r"},
{0x4200, 0xFFC0, OP_THUMB_TST, "tst\t%0-2r, %3-5r"},
{0x4240, 0xFFC0, OP_THUMB_NEG, "neg\t%0-2r, %3-5r"},
{0x4280, 0xFFC0, OP_THUMB_CMP, "cmp\t%0-2r, %3-5r"},
{0x42C0, 0xFFC0, OP_THUMB_CMN, "cmn\t%0-2r, %3-5r"},
{0x4300, 0xFFC0, OP_THUMB_ORR, "orr\t%0-2r, %3-5r"},
{0x4340, 0xFFC0, OP_THUMB_MUL, "mul\t%0-2r, %3-5r"},
{0x4380, 0xFFC0, OP_THUMB_BIC, "bic\t%0-2r, %3-5r"},
{0x43C0, 0xFFC0, OP_THUMB_MVN, "mvn\t%0-2r, %3-5r"},
/* format 13 */
{0xB000, 0xFF80, OP_THUMB_ADD, "add\tsp, #%0-6W"},
{0xB080, 0xFF80, OP_THUMB_SUB, "sub\tsp, #%0-6W"},
/* format 5 */
{0x4700, 0xFF80, OP_THUMB_BX, "bx\t%S"},
{0x4400, 0xFF00, OP_THUMB_ADD, "add\t%D, %S"},
{0x4500, 0xFF00, OP_THUMB_CMP, "cmp\t%D, %S"},
{0x4600, 0xFF00, OP_THUMB_MOV, "mov\t%D, %S"},
/* format 14 */
{0xB400, 0xFE00, OP_THUMB_PUSH, "push\t%N"},
{0xBC00, 0xFE00, OP_THUMB_POP, "pop\t%O"},
/* format 2 */
{0x1800, 0xFE00, OP_THUMB_ADD, "add\t%0-2r, %3-5r, %6-8r"},
{0x1A00, 0xFE00, OP_THUMB_SUB, "sub\t%0-2r, %3-5r, %6-8r"},
{0x1C00, 0xFE00, OP_THUMB_ADD, "add\t%0-2r, %3-5r, #%6-8d"},
{0x1E00, 0xFE00, OP_THUMB_SUB, "sub\t%0-2r, %3-5r, #%6-8d"},
/* format 8 */
{0x5200, 0xFE00, OP_THUMB_STRH, "strh\t%0-2r, [%3-5r, %6-8r]"},
{0x5A00, 0xFE00, OP_THUMB_LDRH, "ldrh\t%0-2r, [%3-5r, %6-8r]"},
{0x5600, 0xFE00, OP_THUMB_LDRSB, "ldrsb\t%0-2r, [%3-5r, %6-8r]"},
{0x5E00, 0xFE00, OP_THUMB_LDRSH, "ldrsh\t%0-2r, [%3-5r, %6-8r]"},
/* format 7 */
{0x5000, 0xFE00, OP_THUMB_STR, "str\t%0-2r, [%3-5r, %6-8r]"},
{0x5400, 0xFE00, OP_THUMB_STRB, "strb\t%0-2r, [%3-5r, %6-8r]"},
{0x5800, 0xFE00, OP_THUMB_LDR, "ldr\t%0-2r, [%3-5r, %6-8r]"},
{0x5C00, 0xFE00, OP_THUMB_LDRB, "ldrb\t%0-2r, [%3-5r, %6-8r]"},
/* format 1 */
{0x0000, 0xF800, OP_THUMB_LSL, "lsl\t%0-2r, %3-5r, #%6-10d"},
{0x0800, 0xF800, OP_THUMB_LSR, "lsr\t%0-2r, %3-5r, #%6-10d"},
{0x1000, 0xF800, OP_THUMB_ASR, "asr\t%0-2r, %3-5r, #%6-10d"},
/* format 3 */
{0x2000, 0xF800, OP_THUMB_MOV, "mov\t%8-10r, #%0-7d"},
{0x2800, 0xF800, OP_THUMB_CMP, "cmp\t%8-10r, #%0-7d"},
{0x3000, 0xF800, OP_THUMB_ADD, "add\t%8-10r, #%0-7d"},
{0x3800, 0xF800, OP_THUMB_SUB, "sub\t%8-10r, #%0-7d"},
/* format 6 */
/* TODO: Disassemble PC relative "LDR rD,=<symbolic>" */
{0x4800, 0xF800, OP_THUMB_LDR, "ldr\t%8-10r, [pc, #%0-7W]\t(%0-7a)"},
/* format 9 */
{0x6000, 0xF800, OP_THUMB_STR, "str\t%0-2r, [%3-5r, #%6-10W]"},
{0x6800, 0xF800, OP_THUMB_LDR, "ldr\t%0-2r, [%3-5r, #%6-10W]"},
{0x7000, 0xF800, OP_THUMB_STRB, "strb\t%0-2r, [%3-5r, #%6-10d]"},
{0x7800, 0xF800, OP_THUMB_LDRB, "ldrb\t%0-2r, [%3-5r, #%6-10d]"},
/* format 10 */
{0x8000, 0xF800, OP_THUMB_STRH, "strh\t%0-2r, [%3-5r, #%6-10H]"},
{0x8800, 0xF800, OP_THUMB_LDRH, "ldrh\t%0-2r, [%3-5r, #%6-10H]"},
/* format 11 */
{0x9000, 0xF800, OP_THUMB_STR, "str\t%8-10r, [sp, #%0-7W]"},
{0x9800, 0xF800, OP_THUMB_LDR, "ldr\t%8-10r, [sp, #%0-7W]"},
/* format 12 */
{0xA000, 0xF800, OP_THUMB_ADD, "add\t%8-10r, pc, #%0-7W\t(adr %8-10r,%0-7a)"},
{0xA800, 0xF800, OP_THUMB_ADD, "add\t%8-10r, sp, #%0-7W"},
/* format 15 */
{0xC000, 0xF800, OP_THUMB_STMIA, "stmia\t%8-10r!,%M"},
{0xC800, 0xF800, OP_THUMB_LDMIA, "ldmia\t%8-10r!,%M"},
/* format 18 */
{0xE000, 0xF800, OP_THUMB_B, "b\t%0-10B"},
/* format 19 */
/* special processing required in disassembler */
{0xF000, 0xF800, OP_THUMB_BL, ""},
{0xF800, 0xF800, OP_THUMB_BL, "second half of BL instruction %0-15x"},
{0xE800, 0xF800, OP_THUMB_BLX, "second half of BLX instruction %0-15x"},
/* format 16 */
{0xD000, 0xFF00, OP_THUMB_B, "beq\t%0-7B"},
{0xD100, 0xFF00, OP_THUMB_B, "bne\t%0-7B"},
{0xD200, 0xFF00, OP_THUMB_B, "bcs\t%0-7B"},
{0xD300, 0xFF00, OP_THUMB_B, "bcc\t%0-7B"},
{0xD400, 0xFF00, OP_THUMB_B, "bmi\t%0-7B"},
{0xD500, 0xFF00, OP_THUMB_B, "bpl\t%0-7B"},
{0xD600, 0xFF00, OP_THUMB_B, "bvs\t%0-7B"},
{0xD700, 0xFF00, OP_THUMB_B, "bvc\t%0-7B"},
{0xD800, 0xFF00, OP_THUMB_B, "bhi\t%0-7B"},
{0xD900, 0xFF00, OP_THUMB_B, "bls\t%0-7B"},
{0xDA00, 0xFF00, OP_THUMB_B, "bge\t%0-7B"},
{0xDB00, 0xFF00, OP_THUMB_B, "blt\t%0-7B"},
{0xDC00, 0xFF00, OP_THUMB_B, "bgt\t%0-7B"},
{0xDD00, 0xFF00, OP_THUMB_B, "ble\t%0-7B"},
/* format 17 */
{0xDE00, 0xFF00, OP_THUMB_UNDEFINED, "undefined"},
{0xDF00, 0xFF00, OP_THUMB_SWI, "swi\t%0-7d"},
/* format 9 */
{0x6000, 0xF800, OP_THUMB_STR, "str\t%0-2r, [%3-5r, #%6-10W]"},
{0x6800, 0xF800, OP_THUMB_LDR, "ldr\t%0-2r, [%3-5r, #%6-10W]"},
{0x7000, 0xF800, OP_THUMB_STRB, "strb\t%0-2r, [%3-5r, #%6-10d]"},
{0x7800, 0xF800, OP_THUMB_LDRB, "ldrb\t%0-2r, [%3-5r, #%6-10d]"},
/* the rest */
{0x0000, 0x0000, OP_THUMB_UNDEFINED, "undefined instruction %0-15x"},
{0x0000, 0x0000, OP_END, 0}
};
#define BDISP23(x,y) ((((((x) & 0x07ff) << 11) | ((y) & 0x07ff)) \
^ 0x200000) - 0x200000) /* 23bit */
static const char * arm_conditional[] =
{"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
"hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
typedef struct
{
const char * name;
const char * description;
const char * reg_names[16];
}
arm_regname;
static arm_regname regnames[] =
{
{ "raw" , "Select raw register names",
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}},
{ "gcc", "Select register names used by GCC",
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }},
{ "std", "Select register names used in ARM's ISA documentation",
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }},
{ "apcs", "Select register names used in the APCS",
{ "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }},
{ "atpcs", "Select register names used in the ATPCS",
{ "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }},
{ "special-atpcs", "Select special register names used in the ATPCS",
{ "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }}
};
/* Default to STD register name set. */
static unsigned int regname_selected = 2;
#define NUM_ARM_REGNAMES NUM_ELEM (regnames)
#define arm_regnames regnames[regname_selected].reg_names
Opcode decode_insn_thumb(uint32_t given)
{
struct thumb_opcode * insn;
for (insn = thumb_opcodes; insn->assembler; insn++) {
if ((given & insn->mask) == insn->value)
return insn->opcode;
}
return OP_THUMB_UNDEFINED;
}
// Generates the disassembly string for the thumb instruction "insn1".
// If "insn1" is a BL or BLX instruction that is the first of two Thumb
// instructions, then insn2 is the second of two instructions. Otherwise,
// insn2 is ignored.
char *disasm_insn_thumb(uint32_t pc, uint32_t insn1, uint32_t insn2, char *result)
{
struct thumb_opcode * insn;
static char buf[80];
char *ptr;
uint32_t addr;
int len;
if (result == NULL)
result = buf;
ptr = result;
for (insn = thumb_opcodes; insn->assembler; insn++) {
if ((insn1 & insn->mask) != insn->value)
continue;
const char * c = insn->assembler;
/* Special processing for Thumb 2-instruction BL sequence: */
if (!*c) { /* Check for empty (not NULL) assembler string. */
uint32_t offset;
offset = BDISP23 (insn1, insn2);
offset = offset * 2 + pc + 4;
if ((insn2 & 0x1000) == 0) {
len = sprintf(ptr, "blx\t");
offset &= 0xfffffffc;
} else {
len = sprintf(ptr, "bl\t");
}
ptr += len;
sprintf(ptr, "0x%x", offset);
return result;
}
insn1 &= 0xffff;
for (; *c; c++) {
if (*c != '%') {
len = sprintf(ptr, "%c", *c);
ptr += len;
continue;
}
int domaskpc = 0;
int domasklr = 0;
switch (*++c) {
case '%':
len = sprintf(ptr, "%%");
ptr += len;
break;
case 'S': {
uint32_t reg;
reg = (insn1 >> 3) & 0x7;
if (insn1 & (1 << 6))
reg += 8;
len = sprintf(ptr, "%s", arm_regnames[reg]);
ptr += len;
break;
}
case 'D': {
uint32_t reg;
reg = insn1 & 0x7;
if (insn1 & (1 << 7))
reg += 8;
len = sprintf(ptr, "%s", arm_regnames[reg]);
ptr += len;
break;
}
case 'T':
len = sprintf(ptr, "%s",
arm_conditional [(insn1 >> 8) & 0xf]);
ptr += len;
break;
case 'N':
if (insn1 & (1 << 8))
domasklr = 1;
/* Fall through. */
case 'O':
if (*c == 'O' && (insn1 & (1 << 8)))
domaskpc = 1;
/* Fall through. */
case 'M': {
int started = 0;
int reg;
len = sprintf(ptr, "{");
ptr += len;
/* It would be nice if we could spot
ranges, and generate the rS-rE format: */
for (reg = 0; (reg < 8); reg++)
if ((insn1 & (1 << reg)) != 0) {
if (started) {
len = sprintf(ptr, ", ");
ptr += len;
}
started = 1;
len = sprintf(ptr, "%s", arm_regnames[reg]);
ptr += len;
}
if (domasklr) {
if (started) {
len = sprintf(ptr, ", ");
ptr += len;
}
started = 1;
len = sprintf(ptr, arm_regnames[14] /* "lr" */);
ptr += len;
}
if (domaskpc) {
if (started) {
len = sprintf(ptr, ", ");
ptr += len;
}
len = sprintf(ptr, arm_regnames[15] /* "pc" */);
ptr += len;
}
len = sprintf(ptr, "}");
ptr += len;
break;
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
int bitstart = *c++ - '0';
int bitend = 0;
while (*c >= '0' && *c <= '9')
bitstart = (bitstart * 10) + *c++ - '0';
switch (*c) {
case '-': {
uint32_t reg;
c++;
while (*c >= '0' && *c <= '9')
bitend = (bitend * 10) + *c++ - '0';
if (!bitend)
abort ();
reg = insn1 >> bitstart;
reg &= (2 << (bitend - bitstart)) - 1;
switch (*c) {
case 'r':
len = sprintf(ptr, "%s", arm_regnames[reg]);
break;
case 'd':
len = sprintf(ptr, "%d", reg);
break;
case 'H':
len = sprintf(ptr, "%d", reg << 1);
break;
case 'W':
len = sprintf(ptr, "%d", reg << 2);
break;
case 'a':
/* PC-relative address -- the bottom two
bits of the address are dropped
before the calculation. */
addr = ((pc + 4) & ~3) + (reg << 2);
len = sprintf(ptr, "0x%x", addr);
break;
case 'x':
len = sprintf(ptr, "0x%04x", reg);
break;
case 'I':
reg = ((reg ^ (1 << bitend)) - (1 << bitend));
len = sprintf(ptr, "%d", reg);
break;
case 'B':
reg = ((reg ^ (1 << bitend)) - (1 << bitend));
addr = reg * 2 + pc + 4;
len = sprintf(ptr, "0x%x", addr);
break;
default:
abort ();
}
ptr += len;
break;
}
case '\'':
c++;
if ((insn1 & (1 << bitstart)) != 0) {
len = sprintf(ptr, "%c", *c);
ptr += len;
}
break;
case '?':
++c;
if ((insn1 & (1 << bitstart)) != 0)
len = sprintf(ptr, "%c", *c++);
else
len = sprintf(ptr, "%c", *++c);
ptr += len;
break;
default:
abort ();
}
break;
}
default:
abort ();
}
}
return result;
}
/* No match. */
abort ();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,332 +0,0 @@
// Copyright 2006 The Android Open Source Project
#ifndef TRACE_READER_BASE_H
#define TRACE_READER_BASE_H
#include <inttypes.h>
#include "trace_common.h"
#include "hash_table.h"
class BBReader;
class InsnReader;
class AddrReader;
class ExcReader;
class PidReader;
class MethodReader;
struct StaticRec {
uint64_t bb_num;
uint32_t bb_addr;
uint32_t num_insns;
};
struct StaticBlock {
StaticRec rec;
uint32_t *insns;
};
struct BBEvent {
uint64_t time;
uint64_t bb_num;
uint32_t bb_addr;
uint32_t *insns;
int num_insns;
int pid;
int is_thumb;
};
struct PidEvent {
uint64_t time;
int rec_type; // record type: fork, context switch, exit ...
int tgid; // thread group id
int pid; // for fork: child pid; for switch: next pid;
// for exit: exit value
uint32_t vstart; // virtual start address (only used with mmap)
uint32_t vend; // virtual end address (only used with mmap)
uint32_t offset; // virtual file offset (only used with mmap)
// Dynamically allocated path to executable (or lib). In the case of
// an mmapped dex file, the path is modified to be more useful for
// comparing against the output of dexlist. For example, instead of this:
// /data/dalvik-cache/system@app@TestHarness.apk@classes.dex
// We convert to this:
// /system/app/TestHarness.apk
char *path;
char *mmap_path; // unmodified mmap path
int argc; // number of args
char **argv; // dynamically allocated array of args
};
struct MethodRec {
uint64_t time;
uint32_t addr;
int pid;
int flags;
};
struct DexSym {
uint32_t addr;
int len;
char *name;
};
struct DexFileList {
char *path;
int nsymbols;
DexSym *symbols;
};
class TraceReaderBase {
public:
TraceReaderBase();
virtual ~TraceReaderBase();
friend class BBReader;
void Open(const char *filename);
void Close();
void WriteHeader(TraceHeader *header);
inline bool ReadBB(BBEvent *event);
int ReadStatic(StaticRec *rec);
int ReadStaticInsns(int num, uint32_t *insns);
TraceHeader *GetHeader() { return header_; }
inline uint64_t ReadInsnTime(uint64_t min_time);
void TruncateLastBlock(uint32_t num_insns);
inline bool ReadAddr(uint64_t *time, uint32_t *addr, int *flags);
inline bool ReadExc(uint64_t *time, uint32_t *current_pc,
uint64_t *recnum, uint32_t *target_pc,
uint64_t *bb_num, uint64_t *bb_start_time,
int *num_insns);
inline bool ReadPidEvent(PidEvent *event);
inline bool ReadMethod(MethodRec *method_record);
StaticBlock *GetStaticBlock(uint64_t bb_num) { return &blocks_[bb_num]; }
uint32_t *GetInsns(uint64_t bb_num) { return blocks_[bb_num].insns; }
uint32_t GetBBAddr(uint64_t bb_num) {
return blocks_[bb_num].rec.bb_addr & ~1;
}
int GetIsThumb(uint64_t bb_num) {
return blocks_[bb_num].rec.bb_addr & 1;
}
void SetPostProcessing(bool val) { post_processing_ = val; }
protected:
virtual int FindCurrentPid(uint64_t time);
int current_pid_;
int next_pid_;
uint64_t next_pid_switch_time_;
PidReader *internal_pid_reader_;
MethodReader *internal_method_reader_;
HashTable<DexFileList*> *dex_hash_;
private:
int FindNumInsns(uint64_t bb_num, uint64_t bb_start_time);
void ReadTraceHeader(FILE *fstream, const char *filename,
const char *tracename, TraceHeader *header);
PidEvent *FindMmapDexFileEvent();
void ParseDexList(const char *filename);
char *static_filename_;
FILE *static_fstream_;
TraceHeader *header_;
BBReader *bb_reader_;
InsnReader *insn_reader_;
AddrReader *load_addr_reader_;
AddrReader *store_addr_reader_;
ExcReader *exc_reader_;
PidReader *pid_reader_;
MethodReader *method_reader_;
ExcReader *internal_exc_reader_;
StaticBlock *blocks_;
bool exc_end_;
uint64_t bb_recnum_;
uint64_t exc_recnum_;
uint64_t exc_bb_num_;
uint64_t exc_time_;
int exc_num_insns_;
bool post_processing_;
bool load_eof_;
uint64_t load_time_;
uint32_t load_addr_;
bool store_eof_;
uint64_t store_time_;
uint32_t store_addr_;
};
class Decoder;
class BBReader {
public:
explicit BBReader(TraceReaderBase *trace);
~BBReader();
void Open(const char *filename);
void Close();
bool ReadBB(BBEvent *event);
private:
struct TimeRec {
BBRec bb_rec;
uint64_t next_time;
};
struct Future {
Future *next;
TimeRec bb;
};
inline Future *AllocFuture();
inline void FreeFuture(Future *future);
inline void InsertFuture(Future *future);
inline int DecodeNextRec();
TimeRec nextrec_;
Future futures_[kMaxNumBasicBlocks];
Future *head_;
Future *free_;
Decoder *decoder_;
bool is_eof_;
TraceReaderBase *trace_;
};
class InsnReader {
public:
InsnReader();
~InsnReader();
void Open(const char *filename);
void Close();
uint64_t ReadInsnTime(uint64_t min_time);
private:
Decoder *decoder_;
uint64_t prev_time_;
uint64_t time_diff_;
int repeat_;
};
class AddrReader {
public:
AddrReader();
~AddrReader();
bool Open(const char *filename, const char *suffix);
void Close();
bool ReadAddr(uint64_t *time, uint32_t *addr);
private:
Decoder *decoder_;
uint32_t prev_addr_;
uint64_t prev_time_;
bool opened_; // true after file is opened
};
class ExcReader {
public:
ExcReader();
~ExcReader();
void Open(const char *filename);
void Close();
bool ReadExc(uint64_t *time, uint32_t *current_pc,
uint64_t *recnum, uint32_t *target_pc,
uint64_t *bb_num, uint64_t *bb_start_time,
int *num_insns);
private:
Decoder *decoder_;
uint64_t prev_time_;
uint64_t prev_recnum_;
};
class PidReader {
public:
PidReader();
~PidReader();
void Open(const char *filename);
void Close();
bool ReadPidEvent(struct PidEvent *event);
void Dispose(struct PidEvent *event);
private:
Decoder *decoder_;
uint64_t prev_time_;
};
class MethodReader {
public:
MethodReader();
~MethodReader();
bool Open(const char *filename);
void Close();
bool ReadMethod(MethodRec *method_record);
private:
Decoder *decoder_;
uint64_t prev_time_;
uint32_t prev_addr_;
int32_t prev_pid_;
bool opened_; // true after file is opened
};
// Reads the next dynamic basic block from the trace.
// Returns true on end-of-file.
inline bool TraceReaderBase::ReadBB(BBEvent *event)
{
bb_recnum_ += 1;
return bb_reader_->ReadBB(event);
}
inline uint64_t TraceReaderBase::ReadInsnTime(uint64_t min_time)
{
return insn_reader_->ReadInsnTime(min_time);
}
inline bool TraceReaderBase::ReadAddr(uint64_t *time, uint32_t *addr, int *flags)
{
if (load_eof_ && store_eof_)
return true;
if (store_eof_ || (!load_eof_ && load_time_ <= store_time_)) {
*time = load_time_;
*addr = load_addr_;
*flags = 0;
load_eof_ = load_addr_reader_->ReadAddr(&load_time_, &load_addr_);
} else {
*time = store_time_;
*addr = store_addr_;
*flags = 1;
store_eof_ = store_addr_reader_->ReadAddr(&store_time_, &store_addr_);
}
return false;
}
inline bool TraceReaderBase::ReadExc(uint64_t *time, uint32_t *current_pc,
uint64_t *recnum, uint32_t *target_pc,
uint64_t *bb_num, uint64_t *bb_start_time,
int *num_insns)
{
return exc_reader_->ReadExc(time, current_pc, recnum, target_pc, bb_num,
bb_start_time, num_insns);
}
inline bool TraceReaderBase::ReadPidEvent(PidEvent *event)
{
return pid_reader_->ReadPidEvent(event);
}
inline bool TraceReaderBase::ReadMethod(MethodRec *method_record)
{
return method_reader_->ReadMethod(method_record);
}
// Duplicates a string, allocating space using new[].
inline char * Strdup(const char *src) {
int len = strlen(src);
char *copy = new char[len + 1];
strcpy(copy, src);
return copy;
}
#endif /* TRACE_READER_BASE_H */

View File

@@ -1,29 +0,0 @@
# 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.
LOCAL_PATH := $(call my-dir)
ifneq ($(TARGET_PRODUCT),sim)
# HAL module implemenation, not prelinked and stored in
# hw/<SENSORS_HARDWARE_MODULE_ID>.<ro.hardware>.so
include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBRARIES := liblog libcutils
LOCAL_SRC_FILES := sensors_qemu.c
LOCAL_MODULE := sensors.goldfish
LOCAL_MODULE_TAGS := debug
include $(BUILD_SHARED_LIBRARY)
endif

View File

@@ -1,597 +0,0 @@
/*
* 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.
*/
/* this implements a sensors hardware library for the Android emulator.
* the following code should be built as a shared library that will be
* placed into /system/lib/hw/sensors.goldfish.so
*
* it will be loaded by the code in hardware/libhardware/hardware.c
* which is itself called from com_android_server_SensorService.cpp
*/
/* we connect with the emulator through the "sensors" qemud service
*/
#define SENSORS_SERVICE_NAME "sensors"
#define LOG_TAG "QemuSensors"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <cutils/log.h>
#include <cutils/native_handle.h>
#include <cutils/sockets.h>
#include <hardware/sensors.h>
#if 0
#define D(...) LOGD(__VA_ARGS__)
#else
#define D(...) ((void)0)
#endif
#define E(...) LOGE(__VA_ARGS__)
#include <hardware/qemud.h>
/** SENSOR IDS AND NAMES
**/
#define MAX_NUM_SENSORS 4
#define SUPPORTED_SENSORS ((1<<MAX_NUM_SENSORS)-1)
#define ID_BASE SENSORS_HANDLE_BASE
#define ID_ACCELERATION (ID_BASE+0)
#define ID_MAGNETIC_FIELD (ID_BASE+1)
#define ID_ORIENTATION (ID_BASE+2)
#define ID_TEMPERATURE (ID_BASE+3)
#define SENSORS_ACCELERATION (1 << ID_ACCELERATION)
#define SENSORS_MAGNETIC_FIELD (1 << ID_MAGNETIC_FIELD)
#define SENSORS_ORIENTATION (1 << ID_ORIENTATION)
#define SENSORS_TEMPERATURE (1 << ID_TEMPERATURE)
#define ID_CHECK(x) ((unsigned)((x)-ID_BASE) < 4)
#define SENSORS_LIST \
SENSOR_(ACCELERATION,"acceleration") \
SENSOR_(MAGNETIC_FIELD,"magnetic-field") \
SENSOR_(ORIENTATION,"orientation") \
SENSOR_(TEMPERATURE,"temperature") \
static const struct {
const char* name;
int id; } _sensorIds[MAX_NUM_SENSORS] =
{
#define SENSOR_(x,y) { y, ID_##x },
SENSORS_LIST
#undef SENSOR_
};
static const char*
_sensorIdToName( int id )
{
int nn;
for (nn = 0; nn < MAX_NUM_SENSORS; nn++)
if (id == _sensorIds[nn].id)
return _sensorIds[nn].name;
return "<UNKNOWN>";
}
static int
_sensorIdFromName( const char* name )
{
int nn;
if (name == NULL)
return -1;
for (nn = 0; nn < MAX_NUM_SENSORS; nn++)
if (!strcmp(name, _sensorIds[nn].name))
return _sensorIds[nn].id;
return -1;
}
/** SENSORS CONTROL DEVICE
**
** This one is used to send commands to the sensors drivers.
** We implement this by sending directly commands to the emulator
** through the QEMUD channel.
**/
typedef struct SensorControl {
struct sensors_control_device_t device;
int fd;
uint32_t active_sensors;
} SensorControl;
/* this must return a file descriptor that will be used to read
* the sensors data (it is passed to data__data_open() below
*/
static native_handle_t*
control__open_data_source(struct sensors_control_device_t *dev)
{
SensorControl* ctl = (void*)dev;
native_handle_t* handle;
if (ctl->fd < 0) {
ctl->fd = qemud_channel_open(SENSORS_SERVICE_NAME);
}
D("%s: fd=%d", __FUNCTION__, ctl->fd);
handle = native_handle_create(1, 0);
handle->data[0] = ctl->fd;
return handle;
}
static int
control__activate(struct sensors_control_device_t *dev,
int handle,
int enabled)
{
SensorControl* ctl = (void*)dev;
uint32_t mask, sensors, active, new_sensors, changed;
char command[128];
int ret;
D("%s: handle=%s (%d) enabled=%d", __FUNCTION__,
_sensorIdToName(handle), handle, enabled);
if (!ID_CHECK(handle)) {
E("%s: bad handle ID", __FUNCTION__);
return -1;
}
mask = (1<<handle);
sensors = enabled ? mask : 0;
active = ctl->active_sensors;
new_sensors = (active & ~mask) | (sensors & mask);
changed = active ^ new_sensors;
if (!changed)
return 0;
snprintf(command, sizeof command, "set:%s:%d",
_sensorIdToName(handle), enabled != 0);
if (ctl->fd < 0) {
ctl->fd = qemud_channel_open(SENSORS_SERVICE_NAME);
}
ret = qemud_channel_send(ctl->fd, command, -1);
if (ret < 0)
return -1;
ctl->active_sensors = new_sensors;
return 0;
}
static int
control__set_delay(struct sensors_control_device_t *dev, int32_t ms)
{
SensorControl* ctl = (void*)dev;
char command[128];
D("%s: dev=%p delay-ms=%d", __FUNCTION__, dev, ms);
snprintf(command, sizeof command, "set-delay:%d", ms);
return qemud_channel_send(ctl->fd, command, -1);
}
/* this function is used to force-stop the blocking read() in
* data__poll. In order to keep the implementation as simple
* as possible here, we send a command to the emulator which
* shall send back an appropriate data block to the system.
*/
static int
control__wake(struct sensors_control_device_t *dev)
{
SensorControl* ctl = (void*)dev;
D("%s: dev=%p", __FUNCTION__, dev);
return qemud_channel_send(ctl->fd, "wake", -1);
}
static int
control__close(struct hw_device_t *dev)
{
SensorControl* ctl = (void*)dev;
close(ctl->fd);
free(ctl);
return 0;
}
/** SENSORS DATA DEVICE
**
** This one is used to read sensor data from the hardware.
** We implement this by simply reading the data from the
** emulator through the QEMUD channel.
**/
typedef struct SensorData {
struct sensors_data_device_t device;
sensors_data_t sensors[MAX_NUM_SENSORS];
int events_fd;
uint32_t pendingSensors;
int64_t timeStart;
int64_t timeOffset;
} SensorData;
/* return the current time in nanoseconds */
static int64_t
data__now_ns(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (int64_t)ts.tv_sec * 1000000000 + ts.tv_nsec;
}
static int
data__data_open(struct sensors_data_device_t *dev, native_handle_t* handle)
{
SensorData* data = (void*)dev;
int i;
D("%s: dev=%p fd=%d", __FUNCTION__, dev, fd);
memset(&data->sensors, 0, sizeof(data->sensors));
for (i=0 ; i<MAX_NUM_SENSORS ; i++) {
data->sensors[i].vector.status = SENSOR_STATUS_ACCURACY_HIGH;
}
data->pendingSensors = 0;
data->timeStart = 0;
data->timeOffset = 0;
data->events_fd = dup(handle->data[0]);
native_handle_close(handle);
native_handle_delete(handle);
return 0;
}
static int
data__data_close(struct sensors_data_device_t *dev)
{
SensorData* data = (void*)dev;
D("%s: dev=%p", __FUNCTION__, dev);
if (data->events_fd > 0) {
close(data->events_fd);
data->events_fd = -1;
}
return 0;
}
static int
pick_sensor(SensorData* data,
sensors_data_t* values)
{
uint32_t mask = SUPPORTED_SENSORS;
while (mask) {
uint32_t i = 31 - __builtin_clz(mask);
mask &= ~(1<<i);
if (data->pendingSensors & (1<<i)) {
data->pendingSensors &= ~(1<<i);
*values = data->sensors[i];
values->sensor = (1<<i);
LOGD_IF(0, "%s: %d [%f, %f, %f]", __FUNCTION__,
(1<<i),
values->vector.x,
values->vector.y,
values->vector.z);
return i;
}
}
LOGE("No sensor to return!!! pendingSensors=%08x", data->pendingSensors);
// we may end-up in a busy loop, slow things down, just in case.
usleep(100000);
return -1;
}
static int
data__poll(struct sensors_data_device_t *dev, sensors_data_t* values)
{
SensorData* data = (void*)dev;
int fd = data->events_fd;
D("%s: data=%p", __FUNCTION__, dev);
// there are pending sensors, returns them now...
if (data->pendingSensors) {
return pick_sensor(data, values);
}
// wait until we get a complete event for an enabled sensor
uint32_t new_sensors = 0;
while (1) {
/* read the next event */
char buff[256];
int len = qemud_channel_recv(data->events_fd, buff, sizeof buff-1);
float params[3];
int64_t event_time;
if (len < 0)
continue;
buff[len] = 0;
/* "wake" is sent from the emulator to exit this loop. This shall
* really be because another thread called "control__wake" in this
* process.
*/
if (!strcmp((const char*)data, "wake")) {
return 0x7FFFFFFF;
}
/* "acceleration:<x>:<y>:<z>" corresponds to an acceleration event */
if (sscanf(buff, "acceleration:%g:%g:%g", params+0, params+1, params+2) == 3) {
new_sensors |= SENSORS_ACCELERATION;
data->sensors[ID_ACCELERATION].acceleration.x = params[0];
data->sensors[ID_ACCELERATION].acceleration.y = params[1];
data->sensors[ID_ACCELERATION].acceleration.z = params[2];
continue;
}
/* "orientation:<azimuth>:<pitch>:<roll>" is sent when orientation changes */
if (sscanf(buff, "orientation:%g:%g:%g", params+0, params+1, params+2) == 3) {
new_sensors |= SENSORS_ORIENTATION;
data->sensors[ID_ORIENTATION].orientation.azimuth = params[0];
data->sensors[ID_ORIENTATION].orientation.pitch = params[1];
data->sensors[ID_ORIENTATION].orientation.roll = params[2];
continue;
}
/* "magnetic:<x>:<y>:<z>" is sent for the params of the magnetic field */
if (sscanf(buff, "magnetic:%g:%g:%g", params+0, params+1, params+2) == 3) {
new_sensors |= SENSORS_MAGNETIC_FIELD;
data->sensors[ID_MAGNETIC_FIELD].magnetic.x = params[0];
data->sensors[ID_MAGNETIC_FIELD].magnetic.y = params[1];
data->sensors[ID_MAGNETIC_FIELD].magnetic.z = params[2];
continue;
}
/* "temperature:<celsius>" */
if (sscanf(buff, "temperature:%g", params+0) == 2) {
new_sensors |= SENSORS_TEMPERATURE;
data->sensors[ID_TEMPERATURE].temperature = params[0];
continue;
}
/* "sync:<time>" is sent after a series of sensor events.
* where 'time' is expressed in micro-seconds and corresponds
* to the VM time when the real poll occured.
*/
if (sscanf(buff, "sync:%lld", &event_time) == 1) {
if (new_sensors) {
data->pendingSensors = new_sensors;
int64_t t = event_time * 1000LL; /* convert to nano-seconds */
/* use the time at the first sync: as the base for later
* time values */
if (data->timeStart == 0) {
data->timeStart = data__now_ns();
data->timeOffset = data->timeStart - t;
}
t += data->timeOffset;
while (new_sensors) {
uint32_t i = 31 - __builtin_clz(new_sensors);
new_sensors &= ~(1<<i);
data->sensors[i].time = t;
}
return pick_sensor(data, values);
} else {
D("huh ? sync without any sensor data ?");
}
continue;
}
D("huh ? unsupported command");
}
}
static int
data__close(struct hw_device_t *dev)
{
SensorData* data = (SensorData*)dev;
if (data) {
if (data->events_fd > 0) {
//LOGD("(device close) about to close fd=%d", data->events_fd);
close(data->events_fd);
}
free(data);
}
return 0;
}
/** MODULE REGISTRATION SUPPORT
**
** This is required so that hardware/libhardware/hardware.c
** will dlopen() this library appropriately.
**/
/*
* the following is the list of all supported sensors.
* this table is used to build sSensorList declared below
* according to which hardware sensors are reported as
* available from the emulator (see get_sensors_list below)
*
* note: numerical values for maxRange/resolution/power were
* taken from the reference AK8976A implementation
*/
static const struct sensor_t sSensorListInit[] = {
{ .name = "Goldfish 3-axis Accelerometer",
.vendor = "The Android Open Source Project",
.version = 1,
.handle = ID_ACCELERATION,
.type = SENSOR_TYPE_ACCELEROMETER,
.maxRange = 2.8f,
.resolution = 1.0f/4032.0f,
.power = 3.0f,
.reserved = {}
},
{ .name = "Goldfish 3-axis Magnetic field sensor",
.vendor = "The Android Open Source Project",
.version = 1,
.handle = ID_MAGNETIC_FIELD,
.type = SENSOR_TYPE_MAGNETIC_FIELD,
.maxRange = 2000.0f,
.resolution = 1.0f,
.power = 6.7f,
.reserved = {}
},
{ .name = "Goldfish Orientation sensor",
.vendor = "The Android Open Source Project",
.version = 1,
.handle = ID_ORIENTATION,
.type = SENSOR_TYPE_ORIENTATION,
.maxRange = 360.0f,
.resolution = 1.0f,
.power = 9.7f,
.reserved = {}
},
{ .name = "Goldfish Temperature sensor",
.vendor = "The Android Open Source Project",
.version = 1,
.handle = ID_TEMPERATURE,
.type = SENSOR_TYPE_TEMPERATURE,
.maxRange = 80.0f,
.resolution = 1.0f,
.power = 0.0f,
.reserved = {}
},
};
static struct sensor_t sSensorList[MAX_NUM_SENSORS];
static uint32_t sensors__get_sensors_list(struct sensors_module_t* module,
struct sensor_t const** list)
{
int fd = qemud_channel_open(SENSORS_SERVICE_NAME);
char buffer[12];
int mask, nn, count;
int ret;
if (fd < 0) {
E("%s: no qemud connection", __FUNCTION__);
return 0;
}
ret = qemud_channel_send(fd, "list-sensors", -1);
if (ret < 0) {
E("%s: could not query sensor list: %s", __FUNCTION__,
strerror(errno));
close(fd);
return 0;
}
ret = qemud_channel_recv(fd, buffer, sizeof buffer-1);
if (ret < 0) {
E("%s: could not receive sensor list: %s", __FUNCTION__,
strerror(errno));
close(fd);
return 0;
}
buffer[ret] = 0;
close(fd);
/* the result is a integer used as a mask for available sensors */
mask = atoi(buffer);
count = 0;
for (nn = 0; nn < MAX_NUM_SENSORS; nn++) {
if (((1 << nn) & mask) == 0)
continue;
sSensorList[count++] = sSensorListInit[nn];
}
D("%s: returned %d sensors (mask=%d)", __FUNCTION__, count, mask);
*list = sSensorList;
return count;
}
static int
open_sensors(const struct hw_module_t* module,
const char* name,
struct hw_device_t* *device)
{
int status = -EINVAL;
D("%s: name=%s", __FUNCTION__, name);
if (!strcmp(name, SENSORS_HARDWARE_CONTROL))
{
SensorControl *dev = malloc(sizeof(*dev));
memset(dev, 0, sizeof(*dev));
dev->device.common.tag = HARDWARE_DEVICE_TAG;
dev->device.common.version = 0;
dev->device.common.module = (struct hw_module_t*) module;
dev->device.common.close = control__close;
dev->device.open_data_source = control__open_data_source;
dev->device.activate = control__activate;
dev->device.set_delay = control__set_delay;
dev->device.wake = control__wake;
dev->fd = -1;
*device = &dev->device.common;
status = 0;
}
else if (!strcmp(name, SENSORS_HARDWARE_DATA)) {
SensorData *dev = malloc(sizeof(*dev));
memset(dev, 0, sizeof(*dev));
dev->device.common.tag = HARDWARE_DEVICE_TAG;
dev->device.common.version = 0;
dev->device.common.module = (struct hw_module_t*) module;
dev->device.common.close = data__close;
dev->device.data_open = data__data_open;
dev->device.data_close = data__data_close;
dev->device.poll = data__poll;
dev->events_fd = -1;
*device = &dev->device.common;
status = 0;
}
return status;
}
static struct hw_module_methods_t sensors_module_methods = {
.open = open_sensors
};
const struct sensors_module_t HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 0,
.id = SENSORS_HARDWARE_MODULE_ID,
.name = "Goldfish SENSORS Module",
.author = "The Android Open Source Project",
.methods = &sensors_module_methods,
},
.get_sensors_list = sensors__get_sensors_list
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 825 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 795 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -1,2 +0,0 @@
# skin-specific hardware values
hw.lcd.density=160

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -1,443 +0,0 @@
parts {
portrait {
background {
image background_port.png
}
}
landscape {
background {
image background_land.png
}
}
device {
display {
width 320
height 480
x 0
y 0
}
}
controls {
background {
image controls.png
}
buttons {
soft-left {
image button.png
x 56
y 142
}
home {
image button.png
x 0
y 142
}
back {
image button.png
x 112
y 142
}
dpad-up {
image arrow_up.png
x 77
y 53
}
dpad-down {
image arrow_down.png
x 77
y 106
}
dpad-left {
image arrow_left.png
x 53
y 53
}
dpad-right {
image arrow_right.png
x 123
y 53
}
dpad-center {
image select.png
x 77
y 81
}
phone-dial {
image button.png
x 0
y 71
}
phone-hangup {
image button.png
x 168
y 71
}
power {
image button.png
x 168
y 0
}
volume-up {
image button.png
x 112
y 0
}
volume-down {
image button.png
x 56
y 0
}
search {
image button.png
x 168
y 142
}
}
}
keyboard {
background {
image keyboard.png
}
buttons {
1 {
image key.png
x 5
y 5
}
2 {
image key.png
x 42
y 5
}
3 {
image key.png
x 79
y 5
}
4 {
image key.png
x 116
y 5
}
5 {
image key.png
x 153
y 5
}
6 {
image key.png
x 190
y 5
}
7 {
image key.png
x 227
y 5
}
8 {
image key.png
x 264
y 5
}
9 {
image key.png
x 301
y 5
}
0 {
image key.png
x 338
y 5
}
q {
image key.png
x 5
y 41
}
w {
image key.png
x 42
y 41
}
e {
image key.png
x 79
y 41
}
r {
image key.png
x 116
y 41
}
t {
image key.png
x 153
y 41
}
y {
image key.png
x 190
y 41
}
u {
image key.png
x 227
y 41
}
i {
image key.png
x 264
y 41
}
o {
image key.png
x 301
y 41
}
p {
image key.png
x 338
y 41
}
a {
image key.png
x 5
y 77
}
s {
image key.png
x 42
y 77
}
d {
image key.png
x 79
y 77
}
f {
image key.png
x 116
y 77
}
g {
image key.png
x 153
y 77
}
h {
image key.png
x 190
y 77
}
j {
image key.png
x 227
y 77
}
k {
image key.png
x 264
y 77
}
l {
image key.png
x 301
y 77
}
DEL {
image key.png
x 338
y 77
}
CAP {
image key.png
x 5
y 113
}
z {
image key.png
x 42
y 113
}
x {
image key.png
x 79
y 113
}
c {
image key.png
x 116
y 113
}
v {
image key.png
x 153
y 113
}
b {
image key.png
x 190
y 113
}
n {
image key.png
x 227
y 113
}
m {
image key.png
x 264
y 113
}
PERIOD {
image key.png
x 301
y 113
}
ENTER {
image key.png
x 338
y 113
}
ALT {
image key.png
x 5
y 149
}
SYM {
image key.png
x 42
y 149
}
AT {
image key.png
x 79
y 149
}
SPACE {
image spacebar.png
x 116
y 149
}
SLASH {
image key.png
x 264
y 149
}
COMMA {
image key.png
x 301
y 149
}
ALT2 {
image key.png
x 338
y 149
}
}
}
}
layouts {
portrait {
width 791
height 534
color 0xe0e0e0
event EV_SW:0:1
part1 {
name portrait
x 0
y 0
}
part2 {
name landscape
x 800
y 0
}
part3 {
name device
x 28
y 27
}
part4 {
name controls
x 476
y 77
}
part5 {
name keyboard
x 395
y 328
}
}
landscape {
width 640
height 601
color 0xe0e0e0
event EV_SW:0:0
# the framework _always_ assume that the DPad
# has been physically rotated in landscape mode.
# however, with this skin, this is not the case
#
dpad-rotation 3
part1 {
name portrait
x 800
y 0
}
part2 {
name landscape
x 0
y 0
}
part3 {
name device
x 80
y 349
rotation 3
}
part4 {
name controls
x 410
y 396
}
part5 {
name keyboard
x 18
y 396
}
}
}
keyboard {
charmap qwerty2
}
network {
speed full
delay none
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 825 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 795 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -1,2 +0,0 @@
# skin-specific hardware values
hw.lcd.density=120

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -1,439 +0,0 @@
parts {
portrait {
background {
image background_port.png
}
}
landscape {
background {
image background_land.png
}
}
device {
display {
width 240
height 320
x 0
y 0
}
}
controls {
background {
image controls.png
}
buttons {
soft-left {
image button.png
x 56
y 142
}
home {
image button.png
x 0
y 142
}
back {
image button.png
x 112
y 142
}
dpad-up {
image arrow_up.png
x 77
y 53
}
dpad-down {
image arrow_down.png
x 77
y 106
}
dpad-left {
image arrow_left.png
x 53
y 53
}
dpad-right {
image arrow_right.png
x 123
y 53
}
dpad-center {
image select.png
x 77
y 81
}
phone-dial {
image button.png
x 0
y 71
}
phone-hangup {
image button.png
x 168
y 71
}
power {
image button.png
x 168
y 0
}
volume-up {
image button.png
x 112
y 0
}
volume-down {
image button.png
x 56
y 0
}
search {
image button.png
x 168
y 142
}
}
}
keyboard {
background {
image keyboard.png
}
buttons {
1 {
image key.png
x 5
y 5
}
2 {
image key.png
x 42
y 5
}
3 {
image key.png
x 79
y 5
}
4 {
image key.png
x 116
y 5
}
5 {
image key.png
x 153
y 5
}
6 {
image key.png
x 190
y 5
}
7 {
image key.png
x 227
y 5
}
8 {
image key.png
x 264
y 5
}
9 {
image key.png
x 301
y 5
}
0 {
image key.png
x 338
y 5
}
q {
image key.png
x 5
y 41
}
w {
image key.png
x 42
y 41
}
e {
image key.png
x 79
y 41
}
r {
image key.png
x 116
y 41
}
t {
image key.png
x 153
y 41
}
y {
image key.png
x 190
y 41
}
u {
image key.png
x 227
y 41
}
i {
image key.png
x 264
y 41
}
o {
image key.png
x 301
y 41
}
p {
image key.png
x 338
y 41
}
a {
image key.png
x 5
y 77
}
s {
image key.png
x 42
y 77
}
d {
image key.png
x 79
y 77
}
f {
image key.png
x 116
y 77
}
g {
image key.png
x 153
y 77
}
h {
image key.png
x 190
y 77
}
j {
image key.png
x 227
y 77
}
k {
image key.png
x 264
y 77
}
l {
image key.png
x 301
y 77
}
DEL {
image key.png
x 338
y 77
}
CAP {
image key.png
x 5
y 113
}
z {
image key.png
x 42
y 113
}
x {
image key.png
x 79
y 113
}
c {
image key.png
x 116
y 113
}
v {
image key.png
x 153
y 113
}
b {
image key.png
x 190
y 113
}
n {
image key.png
x 227
y 113
}
m {
image key.png
x 264
y 113
}
PERIOD {
image key.png
x 301
y 113
}
ENTER {
image key.png
x 338
y 113
}
ALT {
image key.png
x 5
y 149
}
SYM {
image key.png
x 42
y 149
}
AT {
image key.png
x 79
y 149
}
SPACE {
image spacebar.png
x 116
y 149
}
SLASH {
image key.png
x 264
y 149
}
COMMA {
image key.png
x 301
y 149
}
ALT2 {
image key.png
x 338
y 149
}
}
}
}
layouts {
portrait {
width 711
height 435
color 0xe0e0e0
event EV_SW:0:1
part1 {
name portrait
x 0
y 0
}
part2 {
name landscape
x 800
y 0
}
part3 {
name device
x 28
y 58
}
part4 {
name controls
x 396
y 27
}
part5 {
name keyboard
x 315
y 229
}
}
landscape {
width 640
height 522
color 0xe0e0e0
event EV_SW:0:0
dpad-rotation 3
part1 {
name portrait
x 800
y 0
}
part2 {
name landscape
x 0
y 0
}
part3 {
name device
x 160
y 270
rotation 3
}
part4 {
name controls
x 410
y 317
}
part5 {
name keyboard
x 18
y 317
}
}
}
keyboard {
charmap qwerty2
}
network {
speed full
delay none
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 825 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 795 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -1,2 +0,0 @@
# skin-specific hardware values
hw.lcd.density=120

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