1313 * limitations under the License.
1414 */
1515
16- import { spawn , spawnSync , SpawnSyncReturns } from 'child_process' ;
16+ import { spawn , spawnSync , SpawnSyncReturns } from 'child_process' ;
1717import path from 'path' ;
1818import { convertStr2RunningState , Hap , HapRunningState } from '../model/hap' ;
1919import { HdcCmdError } from '../error/error' ;
2020import { getLogger } from 'log4js' ;
2121
2222const logger = getLogger ( ) ;
2323
24- export const NEWLINE = / \r \n | \n / ;
25- const MEMDUMPER = '/data/local/tmp/memdumper' ;
26-
27- export interface HdcTargetInfo {
28- serial : string ;
29- transport : string ;
30- state : string ;
31- host : string ;
32- type : string ;
33- }
34-
35- export class Hdc {
36- private connectkey : string | undefined ;
37-
38- constructor ( connectkey : string | undefined = undefined ) {
39- this . connectkey = connectkey ;
40- this . initDeviceEnv ( ) ;
41- }
42-
43- private initDeviceEnv ( ) : void {
44- if ( ! this . hasFile ( MEMDUMPER ) ) {
45- let memdumpFile = path . join ( __dirname , '..' , '..' , 'res/memdumper/memdumper' ) ;
46- this . sendFile ( memdumpFile , MEMDUMPER ) ;
47- this . excuteShellCommandSync ( `chmod +x ${ MEMDUMPER } ` ) ;
48- }
49- }
24+ export const NEWLINE = / \r \n | \n / ;
25+ const MEMDUMPER = '/data/local/tmp/memdumper' ;
26+
27+ export interface HdcTargetInfo {
28+ serial : string ;
29+ transport : string ;
30+ state : string ;
31+ host : string ;
32+ type : string ;
33+ }
34+
35+ export class Hdc {
36+ private connectkey : string | undefined ;
37+
38+ constructor ( connectkey : string | undefined = undefined ) {
39+ this . connectkey = connectkey ;
40+ this . initDeviceEnv ( ) ;
41+ }
42+
43+ private initDeviceEnv ( ) : void {
44+ if ( ! this . hasFile ( MEMDUMPER ) ) {
45+ let memdumpFile = path . join ( __dirname , '..' , '..' , 'res/memdumper/memdumper' ) ;
46+ this . sendFile ( memdumpFile , MEMDUMPER ) ;
47+ this . excuteShellCommandSync ( `chmod +x ${ MEMDUMPER } ` ) ;
48+ }
49+ }
5050
5151 sendFile ( local : string , remote : string ) : number {
5252 let output = this . excuteSync ( 'file' , 'send' , local , remote ) ;
@@ -222,11 +222,14 @@ export class Hdc {
222222 *
223223 * @param pid process pid
224224 * @param prefix output prefix file name
225- * @param fileReg normal app match regex: /^\/data\/storage\/el1\/bundle\/[\S]*[.hap|.hsp]$/
225+ * @param fileReg normal app match regex: /^\/data\/storage\/el1\/bundle\/.*\.(hap|hsp|so)$/
226+ * @param maps optional pre-fetched maps, if provided, will skip getProcMaps call
226227 */
227- memdump ( pid : number , remoteOutput : string , fileReg : RegExp ) : void {
228+ memdump ( pid : number , remoteOutput : string , fileReg : RegExp , maps ?: { start : string ; end : string ; file : string } [ ] ) : void {
228229 let idxMap : Map < string , number > = new Map ( ) ;
229- let maps = this . getProcMaps ( pid , fileReg ) ;
230+ if ( ! maps ) {
231+ maps = this . getProcMaps ( pid , fileReg ) ;
232+ }
230233 for ( const map of maps ) {
231234 let idx = 0 ;
232235 if ( idxMap . has ( map . file ) ) {
@@ -255,6 +258,11 @@ export class Hdc {
255258 }
256259
257260 getProcMaps ( pid : number , fileReg ?: RegExp ) : { start : string ; end : string ; file : string } [ ] {
261+ const result = this . getProcMapsWithRaw ( pid , fileReg ) ;
262+ return result . maps ;
263+ }
264+
265+ getProcMapsWithRaw ( pid : number , fileReg ?: RegExp ) : { maps : { start : string ; end : string ; file : string } [ ] ; rawOutput : string } {
258266 let maps : { start : string ; end : string ; file : string } [ ] = [ ] ;
259267 let cmd = `cat /proc/${ pid } /maps` ;
260268
@@ -272,13 +280,17 @@ export class Hdc {
272280 maps . length === 0 ||
273281 ! ( `0x${ addr [ 0 ] } ` === maps [ maps . length - 1 ] . end && file === maps [ maps . length - 1 ] . file )
274282 ) {
283+ // 当前区间与上一条不连续,如该文件已存在于结果中,则忽略后续非连续映射,避免同一文件多段地址
284+ if ( maps . find ( ( m ) => m . file === file ) ) {
285+ continue ;
286+ }
275287 maps . push ( { start : `0x${ addr [ 0 ] } ` , end : `0x${ addr [ 1 ] } ` , file : file } ) ;
276288 } else {
277289 maps [ maps . length - 1 ] . end = `0x${ addr [ 1 ] } ` ;
278290 }
279291 }
280292 }
281- return maps ;
293+ return { maps, rawOutput : output } ;
282294 }
283295
284296 startBftp ( hap : Hap ) : { pid : number ; port : number } {
@@ -395,11 +407,11 @@ export class Hdc {
395407 return this . excute ( 'shell' , ...args ) ;
396408 }
397409
398- async excute ( command : string , ...params : string [ ] ) : Promise < string > {
399- return new Promise ( ( resolve ) => {
400- let args : string [ ] = [ ] ;
401- if ( this . connectkey ) {
402- args . push ( ...[ '-t' , this . connectkey ] ) ;
410+ async excute ( command : string , ...params : string [ ] ) : Promise < string > {
411+ return new Promise ( ( resolve ) => {
412+ let args : string [ ] = [ ] ;
413+ if ( this . connectkey ) {
414+ args . push ( ...[ '-t' , this . connectkey ] ) ;
403415 }
404416 args . push ( ...[ command , ...params ] ) ;
405417 logger . debug ( `hdc excute: ${ JSON . stringify ( args ) } ` ) ;
@@ -422,49 +434,49 @@ export class Hdc {
422434 if ( code !== 0 ) {
423435 logger . debug ( `hdc process exited with code ${ code } ` ) ;
424436 }
425- } ) ;
426- } ) ;
427- }
428-
429- static listTargets ( ) : HdcTargetInfo [ ] {
430- const result = spawnSync ( 'hdc' , [ 'list' , 'targets' , '-v' ] , { encoding : 'utf-8' , shell : true } ) ;
431- if ( result . error ) {
432- throw new Error ( `Failed to execute hdc: ${ result . error . message } ` ) ;
433- }
434-
435- const stderr = ( result . stderr || '' ) . trim ( ) ;
436- const stdout = ( result . stdout || '' ) . trim ( ) ;
437- if ( ! stdout && stderr ) {
438- throw new Error ( stderr ) ;
439- }
440-
441- const entries : HdcTargetInfo [ ] = [ ] ;
442- const lines = stdout . split ( NEWLINE ) ;
443- for ( const rawLine of lines ) {
444- const line = rawLine . trim ( ) ;
445- if ( ! line ) {
446- continue ;
447- }
448- const lower = line . toLowerCase ( ) ;
449- if ( lower . startsWith ( 'list targets' ) || lower . startsWith ( 'total' ) ) {
450- continue ;
451- }
452- if ( line . startsWith ( '[Fail]' ) ) {
453- throw new Error ( line ) ;
454- }
455- const tokens = line . split ( / \s + / ) . filter ( ( token ) => token . length > 0 ) ;
456- if ( tokens . length < 3 ) {
457- continue ;
458- }
459- const [ serial , transport = '' , state = '' , host = '' , type = '' ] = tokens ;
460- entries . push ( {
461- serial,
462- transport,
463- state,
464- host,
465- type,
466- } ) ;
467- }
468- return entries ;
469- }
470- }
437+ } ) ;
438+ } ) ;
439+ }
440+
441+ static listTargets ( ) : HdcTargetInfo [ ] {
442+ const result = spawnSync ( 'hdc' , [ 'list' , 'targets' , '-v' ] , { encoding : 'utf-8' , shell : true } ) ;
443+ if ( result . error ) {
444+ throw new Error ( `Failed to execute hdc: ${ result . error . message } ` ) ;
445+ }
446+
447+ const stderr = ( result . stderr || '' ) . trim ( ) ;
448+ const stdout = ( result . stdout || '' ) . trim ( ) ;
449+ if ( ! stdout && stderr ) {
450+ throw new Error ( stderr ) ;
451+ }
452+
453+ const entries : HdcTargetInfo [ ] = [ ] ;
454+ const lines = stdout . split ( NEWLINE ) ;
455+ for ( const rawLine of lines ) {
456+ const line = rawLine . trim ( ) ;
457+ if ( ! line ) {
458+ continue ;
459+ }
460+ const lower = line . toLowerCase ( ) ;
461+ if ( lower . startsWith ( 'list targets' ) || lower . startsWith ( 'total' ) ) {
462+ continue ;
463+ }
464+ if ( line . startsWith ( '[Fail]' ) ) {
465+ throw new Error ( line ) ;
466+ }
467+ const tokens = line . split ( / \s + / ) . filter ( ( token ) => token . length > 0 ) ;
468+ if ( tokens . length < 3 ) {
469+ continue ;
470+ }
471+ const [ serial , transport = '' , state = '' , host = '' , type = '' ] = tokens ;
472+ entries . push ( {
473+ serial,
474+ transport,
475+ state,
476+ host,
477+ type,
478+ } ) ;
479+ }
480+ return entries ;
481+ }
482+ }
0 commit comments