[Vm-dev] VM Maker: VMMaker.oscog-eem.3207.mcz

commits at source.squeak.org commits at source.squeak.org
Wed Jul 13 01:21:53 UTC 2022


Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.3207.mcz

==================== Summary ====================

Name: VMMaker.oscog-eem.3207
Author: eem
Time: 12 July 2022, 6:21:39.357594 pm
UUID: 7ff2cdc8-1f14-45a3-a63a-2d7457bc0c77
Ancestors: VMMaker.oscog-eem.3206

Add a primitive to answer the text symbols in a module, now that modern MacOS's hide the system's dylibs and break the old nm(1) approach.

Slang: fix a bug in determining the struct/pointer type for an expression in a plugin that overrides InterpreterPlugin class>>#isStructType: to add its own struct types.

=============== Diff against VMMaker.oscog-eem.3206 ===============

Item was changed:
  ----- Method: TSendNode>>structTargetKindIn: (in category 'testing') -----
  structTargetKindIn: aCodeGen
  	"Answer if the recever evaluates to a struct or struct pointer
  	 and hence can be dereferenced using . or ->.  Answer any of
  	 #struct #pointer or nil.  Right now we don't need or support
  	 structure return so this method answers either #pointer or nil."
  	selector == #cCoerceSimple:to: ifTrue:
  		[^(VMStructType isTypePointerToStruct: arguments last value) ifTrue:
  			[#pointer]].
  
  	selector == #addressOf: ifTrue:
  		[^#pointer].
  
  	selector == #at: ifTrue:
  		[receiver isVariable ifTrue:
  			[(aCodeGen typeOfVariable: receiver name) ifNotNil:
+ 				[:type| 
- 				[:type| | derefType |
  				 type last = $* ifFalse:
  					[^receiver structTargetKindIn: aCodeGen].
+ 				 (aCodeGen structTargetKindForDeclaration: type allButLast) ifNotNil:
+ 					[:kind| ^kind]]].
- 				 (VMStructType isTypeStruct: (aCodeGen
- 											extractTypeFor: receiver name
- 											fromDeclaration: type allButLast)) ifTrue:
- 						[^#struct]]].
  		(receiver structTargetKindIn: aCodeGen) ifNotNil:
  			[:kind| ^kind]].
  
  	(aCodeGen selectorReturnsPointerToStruct: selector) ifTrue:
  		[^#pointer].
  
  	(aCodeGen selectorReturnsStruct: selector) ifTrue:
  		[^#struct].
  
  	^nil!

Item was changed:
  ----- Method: VMPluginCodeGenerator>>structTargetKindForDeclaration: (in category 'C code generator') -----
  structTargetKindForDeclaration: decl "<String>"
  	^(super structTargetKindForDeclaration: decl) ifNil:
  		[pluginClass ifNotNil:
  			[| isPointer |
  			 (pluginClass isStructType: ((isPointer := decl last == $*)
+ 											ifTrue: [decl allButLast]
+ 											ifFalse: [decl]) withBlanksTrimmed) ifTrue:
- 											ifTrue: [decl allButLast withBlanksTrimmed]
- 											ifFalse: [decl])) ifTrue:
  				[isPointer
  					ifTrue: [#pointer]
  					ifFalse: [#struct]]]]!

Item was added:
+ ----- Method: VMProfileMacSupportPlugin class>>isStructType: (in category 'translation') -----
+ isStructType: typeName
+ 	^#('struct section' 'struct section_64' 'Dl_info') includes: typeName!

Item was changed:
  ----- Method: VMProfileMacSupportPlugin>>primitiveExecutableModulesAndOffsets (in category 'primitives') -----
  primitiveExecutableModulesAndOffsets
  	"Answer an Array of quads for executable modules (the VM executable
  	 and loaded libraries).  Each quad is the module's name, its vm address
  	 relocation in memory, the (unrelocated) start address, and the size."
  	| nimages resultObj name valueObj nameObjData slide start size |
  	<export: true>
  	<var: #name type: 'const char *'>
  	<var: #nameObjData type: #'char *'>
  	<var: #h type: 'const struct mach_header *'>
  	<var: #h64 type: 'const struct mach_header_64 *'>
  	<var: #s64 type: 'const struct section_64 *'>
  	<var: #s type: 'const struct section *'>
  	<var: #start type: 'usqIntptr_t'>
  	<var: #slide type: 'usqIntptr_t'>
  	<var: #size type: 'usqIntptr_t'>
+ 
+ 	nimages := self _dyld_image_count.
- 	self cppIf: #'MAC_OS_X_VERSION_MIN_REQUIRED' <= #'MAC_OS_X_VERSION_10_4'
- 		ifTrue: "_dyld_present was deprecated in 10.5"
- 			[(self cCode: '_dyld_present()' inSmalltalk: false) ifFalse:
- 				[^interpreterProxy primitiveFail]].
- 	nimages := self cCode: '_dyld_image_count()' inSmalltalk: 0.
  	resultObj := interpreterProxy instantiateClass: interpreterProxy classArray indexableSize: nimages * 4.
  	resultObj = 0 ifTrue:
  		[^interpreterProxy primitiveFail].
  
  	interpreterProxy pushRemappableOop: resultObj.
  	0 to: nimages - 1 do:
  		[:i|
  		start := size := -1. "impossible start & size"
+ 		name := self _dyld_get_image_name: i.
+ 		slide   := self _dyld_get_image_vmaddr_slide: i.
- 		name := self cCode: '_dyld_get_image_name(i)' inSmalltalk: 0.
- 		slide   := self cCode: '_dyld_get_image_vmaddr_slide(i)' inSmalltalk: 0.
  		self cppIf: #'__x86_64__' | #'__arm64__'
  			ifTrue:
+ 				[(self cCoerceSimple: (self _dyld_get_image_header: i)
+ 					to: #'const struct mach_header_64 *') ifNotNil:
- 				[(self cCode: '(const struct mach_header_64 *)_dyld_get_image_header(i)' inSmalltalk: nil) ifNotNil:
  					[:h64|
+ 					 (self getsectbynamefromheader_64: h64 _: #SEG_TEXT _: #SECT_TEXT) ifNotNil:
- 					 (self cCode: 'getsectbynamefromheader_64(h64,SEG_TEXT,SECT_TEXT)' inSmalltalk: nil) ifNotNil:
  						[:s64|
+ 						 start := s64 addr.
+ 						 size := s64 size]]]
- 						 start := self cCode: 's64->addr' inSmalltalk: 0.
- 						 size := self cCode: 's64->size' inSmalltalk: 0]]]
  			ifFalse:
+ 				[(self _dyld_get_image_header: i) ifNotNil:
- 				[(self cCode: '_dyld_get_image_header(i)' inSmalltalk: nil) ifNotNil:
  					[:h|
+ 					 (self getsectbynamefromheader: h _: #SEG_TEXT _: #SECT_TEXT) ifNotNil:
- 					 (self cCode: 'getsectbynamefromheader(h,SEG_TEXT,SECT_TEXT)' inSmalltalk: nil) ifNotNil:
  						[:s|
+ 						 start := s addr.
+ 						 size := s size]]].
- 						 start := self cCode: 's->addr' inSmalltalk: 0.
- 						 size := self cCode: 's->size' inSmalltalk: 0]]].
  
  		valueObj := interpreterProxy
  						instantiateClass: interpreterProxy classString
  						indexableSize: (self strlen: name).
  		interpreterProxy failed ifTrue:
  			[interpreterProxy popRemappableOop.
+ 			 ^interpreterProxy primitiveFailFor: PrimErrNoMemory].
- 			 ^interpreterProxy primitiveFail].
  		interpreterProxy storePointer: i * 4 ofObject: interpreterProxy topRemappableOop withValue: valueObj.
  		nameObjData := interpreterProxy arrayValueOf: valueObj.
  		self memcpy: nameObjData _: name _: (self strlen: name).
  
  		valueObj := interpreterProxy signedMachineIntegerFor: slide.
  		interpreterProxy failed ifTrue:
  			[interpreterProxy popRemappableOop.
+ 			 ^interpreterProxy primitiveFailFor: PrimErrNoMemory].
- 			 ^interpreterProxy primitiveFail].
  		interpreterProxy storePointer: i * 4 + 1 ofObject: interpreterProxy topRemappableOop withValue: valueObj.
  
  		valueObj := interpreterProxy positiveMachineIntegerFor: start.
  		interpreterProxy failed ifTrue:
  			[interpreterProxy popRemappableOop.
+ 			 ^interpreterProxy primitiveFailFor: PrimErrNoMemory].
- 			 ^interpreterProxy primitiveFail].
  		interpreterProxy storePointer: i * 4 + 2 ofObject: interpreterProxy topRemappableOop withValue: valueObj.
  
  		valueObj := interpreterProxy positiveMachineIntegerFor: size.
  		interpreterProxy failed ifTrue:
  			[interpreterProxy popRemappableOop.
+ 			 ^interpreterProxy primitiveFailFor: PrimErrNoMemory].
- 			 ^interpreterProxy primitiveFail].
  		interpreterProxy storePointer: i * 4 + 3 ofObject: interpreterProxy topRemappableOop withValue: valueObj].
  
+ 	^interpreterProxy methodReturnValue: interpreterProxy popRemappableOop!
- 	resultObj := interpreterProxy popRemappableOop.
- 	^interpreterProxy pop: 1 thenPush: resultObj!

Item was added:
+ ----- Method: VMProfileMacSupportPlugin>>primitiveTextSymbols (in category 'primitives') -----
+ primitiveTextSymbols
+ 	"Answer an Array of pairs of address, name, for text symbols in the n'th loaded module,
+ 	 as defined by the _dyld_image_count enumeration."
+ 	| moduleIndex resultObj slide start end dlInfos dlInfo ndlInfos index last_saddr increment |
+ 	<export: true>
+ 	<var: 'nameObjData' type: #'char *'>
+ 	<var: 'h' type: 'const struct mach_header *'>
+ 	<var: 'h64' type: 'const struct mach_header_64 *'>
+ 	<var: 's64' type: 'const struct section_64 *'>
+ 	<var: 's' type: 'const struct section *'>
+ 	<var: 'start' type: #'usqIntptr_t'>
+ 	<var: 'slide' type: #'usqIntptr_t'>
+ 	<var: 'end' type: #'usqIntptr_t'>
+ 	<var: 'dlInfos' type: 'Dl_info *'>
+ 	<var: 'dlInfo' type: 'Dl_info'>
+ 	<var: 'last_saddr' type: #'void *'>
+ 
+ 	moduleIndex := interpreterProxy stackValue: 0.
+ 	((interpreterProxy isIntegerObject: moduleIndex)
+ 	 and: [(moduleIndex := interpreterProxy integerValueOf: moduleIndex) >= 0
+ 	 and: [(self _dyld_get_image_name: moduleIndex) notNil]]) ifFalse:
+ 		[^interpreterProxy primitiveFailFor: PrimErrBadArgument].
+ 
+ 	start := 0.
+ 	slide := self _dyld_get_image_vmaddr_slide: moduleIndex.
+ 	self cppIf: #'__x86_64__' | #'__arm64__'
+ 		ifTrue:
+ 			[(self cCoerceSimple: (self _dyld_get_image_header: moduleIndex)
+ 				to: #'const struct mach_header_64 *') ifNotNil:
+ 				[:h64|
+ 				 (self getsectbynamefromheader_64: h64 _: #SEG_TEXT _: #SECT_TEXT) ifNotNil:
+ 					[:s64|
+ 					 start := s64 addr + slide.
+ 					 end := start + s64 size]]]
+ 		ifFalse:
+ 			[(self _dyld_get_image_header: moduleIndex) ifNotNil:
+ 				[:h|
+ 				 (self getsectbynamefromheader: h _: #SEG_TEXT _: #SECT_TEXT) ifNotNil:
+ 					[:s|
+ 					 start := s addr.
+ 					 end := start + s size]]].
+ 	start = 0 ifTrue:
+ 		[^interpreterProxy primitiveFailFor: PrimErrOperationFailed].
+ 
+ 	(dlInfos := self malloc: (self sizeof: #'Dl_info') * (ndlInfos := increment := 1024)) ifNil:
+ 		[^interpreterProxy primitiveFailFor: PrimErrNoCMemory].
+ 	index := 0.
+ 	last_saddr := nil.
+ 
+ 	"Yes, dear reader, one could use binary search to reduce the amount of effort.  But when this author
+ 	 attempted to do so, he achieved only a marginal improvement for a substantial increase in complexity.
+ 	 So KISS and do a linear scan, looking ahead 64 bytes to reduce overhead as simply as possible. 64 gave
+ 	 best results when tried on the VM module of an ARMv8/aarch64 VM; about 2.5x a naive step by sizeof(void *)."
+ 	[start < end and: [(self dladdr: start asVoidPointer _: dlInfos + index) ~= 0]] whileTrue:
+ 		[(start + 64 < end
+ 		 and: [(self dladdr: (start + 64) asVoidPointer _: (self addressOf: dlInfo)) ~= 0
+ 		 and: [dlInfo dli_saddr = (dlInfos at: index) dli_saddr]])
+ 			ifTrue: [start := start + 64 + (self sizeof: #'void *')]
+ 			ifFalse: [start := start + (self sizeof: #'void *')].
+ 		 last_saddr ~= (dlInfos at: index) dli_saddr ifTrue:
+ 			[last_saddr := (dlInfos at: index) dli_saddr.
+ 			 (index := index + 1) = ndlInfos ifTrue:
+ 				[dlInfos := self reallocf: dlInfos _: (self sizeof: #'Dl_info') * (ndlInfos + increment).
+ 				 dlInfos ifNil:
+ 					[^interpreterProxy primitiveFailFor: PrimErrNoCMemory].
+ 				 ndlInfos := ndlInfos + increment.
+ 				 increment := increment * 2]]].
+ 
+ 	resultObj := interpreterProxy instantiateClass: interpreterProxy classArray indexableSize: index * 2.
+ 	resultObj = 0 ifTrue:
+ 		[self free: dlInfos.
+ 		 ^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+ 	interpreterProxy pushRemappableOop: resultObj.
+ 	ndlInfos := index.
+ 	index := 0.
+ 
+ 	[index < ndlInfos] whileTrue:
+ 		[| valueObj nameObjData |
+ 		valueObj := interpreterProxy positiveMachineIntegerFor: (dlInfos at: index) dli_saddr.
+ 		interpreterProxy failed ifTrue:
+ 			[self free: dlInfos.
+ 			 interpreterProxy popRemappableOop.
+ 			 ^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+ 		interpreterProxy storePointer: index * 2 ofObject: interpreterProxy topRemappableOop withValue: valueObj.
+ 
+ 		valueObj := interpreterProxy
+ 						instantiateClass: interpreterProxy classString
+ 						indexableSize: (self strlen: (dlInfos at: index) dli_sname).
+ 		interpreterProxy failed ifTrue:
+ 			[self free: dlInfos.
+ 			 interpreterProxy popRemappableOop.
+ 			 ^interpreterProxy primitiveFailFor: PrimErrNoMemory].
+ 		interpreterProxy storePointer: index * 2 + 1 ofObject: interpreterProxy topRemappableOop withValue: valueObj.
+ 		nameObjData := interpreterProxy arrayValueOf: valueObj.
+ 		self memcpy: nameObjData _: (dlInfos at: index) dli_sname _: (self strlen: (dlInfos at: index) dli_sname).
+ 
+ 		index := index + 1].
+ 
+ 	self free: dlInfos.
+ 	^interpreterProxy methodReturnValue: interpreterProxy popRemappableOop!



More information about the Vm-dev mailing list